文章目录
- 天梯赛
- L1-001 Hello World (5分)
- L1-002 打印沙漏 (20分)
- L1-003 个位数统计 (15分)
- L1-004 计算摄氏温度 (5分)
- L1-005 考试座位号 (15分)
- L1-006 连续因子 (20分)
- L1-007 念数字 (10分)
- L1-008 求整数段和 (10分)
- L1-009 N个数求和 (20分)
- L1-010 比较大小 (10分)
- L1-011 A-B (20分)
- L1-012 计算指数 (5分)
- L1-013 计算阶乘和 (10分)
- L1-014 简单题 (5分)
- L1-015 跟奥巴马一起画方块 (15分)
- L1-016 查验身份证 (15分)
- L1-017 到底有多二 (15分)
- L1-018 大笨钟 (10分)
- L1-019 谁先倒 (15分)
- L1-020 帅到没朋友 (20分)
天梯赛
L1-001 Hello World (5分)
这道超级简单的题目没有任何输入。
你只需要在一行中输出著名短句“Hello World!”就可以了。
输入样例:
无
输出样例:
Hello World!
答案:
#include <iostream>
using namespace std;
int main()
{
cout << "Hello World!" << endl;
return 0;
}
L1-002 打印沙漏 (20分)
本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印
*****
***
*
***
*****
所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。
给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。
输入格式:
输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。
输出格式:
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
输入样例:
19 *
输出样例:
*****
***
*
***
*****
2
答案:
注意每一行字符后不可以加空格,否则无法通过测试,会出现格式错误
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int n;
char c;
scanf("%d %c",&n, &c);
int m = (n + 1)/2;
int i = 0;
while(i*i <= m)
i++;
int k = --i;
for(int j = 0; j < k; j++){ //打印上半部分
for(int q = 0; q < j; q++){
printf(" ");
}
for(int p = 0; p < 2*i-1; p++){
printf("%c",c);
}
/*for(int q = 0; q < j; q++){
printf(" ");
}
*/ //字符后不可以有空格
printf("\n");
i--;
}
i++;
i++; //i+=2;
for(int j = k -1; j > 0; j--){ //打印下半部分
for(int q = j-1; q > 0; q--){
printf(" ");
}
for(int p = 0; p < 2*i-1; p++){
printf("%c",c);
}
/*for(int q = j-1; q > 0; q--){
printf(" ");
}
*/ //字符后不可以有空格
printf("\n");
i++;
}
i = (i-1)*(i-1)*2 - 1;
m = n - i;
printf("%d", m); //printf("%d", n - i);
}
L1-003 个位数统计 (15分)
给定一个 k 位整数 ,请编写程序统计每种不同的个位数字出现的次数。例如:给定 ,则有 2 个 0,3 个 1,和 1 个 3。
输入格式:
每个输入包含 1 个测试用例,即一个不超过 1000 位的正整数 N。
输出格式:
对 N 中每一种不同的个位数字,以 D:M
的格式在一行中输出该位数字 D
及其在 N 中出现的次数 M
。要求按 D
的升序输出。
输入样例:
100311
输出样例:
0:2
1:3
3:1
答案1
此答案无法通过第三个测试点,因未注意到N的位数,正整数位数过多时无法用int 或 long int 表示
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int N = 0;
int i = 0;
scanf("%d", &N);
int a[10] = {0};
//printf("1\n");
while(N / 10 != 0){
i = N % 10;
a[i]++;
N = N / 10;
//printf("2\n");
}
a[N]++;
for(int j = 0; j <= 9; j++){
if(a[j] != 0){
printf("%d:%d\n",j, a[j]);
}
}
return 0;
}
答案2
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
int maxn = 1010;
int main(){
char str[maxn];
int a[10];
int i, len;
while(cin>>str){ //while(scanf("%s",str)!=EOF)
len = strlen(str);
memset(a, 0, sizeof(a));
for(i = 0; i < len; i++){
a[str[i] - '0']++;
}
for(i = 0; i < 10; i++){
if(a[i] != 0){
printf("%d:%d\n", i, a[i]);
}
}
}
return 0;
}
cin>>str代表获取键盘输入的值赋值给变量str,将cin>>str置于while的循环条件内即while(cin>>str),将会一直测试输入流是否正常。
如果输入流正常,就会继续循环获取键盘值,如果输入流错误,或者达到文件末尾(在windows下Ctrl+Z,在Linux下Ctrl+D),该循环就会终止。
等同于C中的 while(scanf("%s",str)!=EOF)
L1-004 计算摄氏温度 (5分)
给定一个华氏温度 ,本题要求编写程序,计算对应的摄氏温度 。计算公式: 。题目保证输入与输出均在整型范围内。
输入格式:
输入在一行中给出一个华氏温度。
输出格式:
在一行中按照格式“Celsius = C”输出对应的摄氏温度C的整数值。
输入样例:
150
输出样例:
Celsius = 65
答案
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int f, c;
scanf("%d", &f);
c = 5 * (f - 32)/9;
printf("Celsius = %d", c);
return 0;
}
L1-005 考试座位号 (15分)
每个 PAT 考生在参加考试时都会被分配两个座位号,一个是试机座位,一个是考试座位。正常情况下,考生在入场时先得到试机座位号码,入座进入试机状态后,系统会显示该考生的考试座位号码,考试时考生需要换到考试座位就座。但有些考生迟到了,试机已经结束,他们只能拿着领到的试机座位号码求助于你,从后台查出他们的考试座位号码。
输入格式:
输入第一行给出一个正整数 N(≤1000),随后 N 行,每行给出一个考生的信息:准考证号 试机座位号 考试座位号
。其中准考证号
由 16 位数字组成,座位从 1 到 N 编号。输入保证每个人的准考证号都不同,并且任何时候都不会把两个人分配到同一个座位上。
考生信息之后,给出一个正整数 M(≤N),随后一行中给出 M 个待查询的试机座位号码,以空格分隔。
输出格式:
对应每个需要查询的试机座位号码,在一行中输出对应考生的准考证号和考试座位号码,中间用 1 个空格分隔。
输入样例:
4
3310120150912233 2 4
3310120150912119 4 1
3310120150912126 1 3
3310120150912002 3 2
2
3 4
输出样例:
3310120150912002 2
3310120150912119 1
答案1
数组方式
#include <iostream>
#include <stdio.h>
using namespace std;
const int MAX = 1010;
char s[MAX+1][16];
int a[MAX+1];
int b[MAX+1];
int main()
{
int N, x, y;
scanf("%d", &N);
for(int i = 0; i < N; i++){
scanf("%s %d %d", &s[i], &a[i], &b[i]);
}
scanf("%d", &x);
for(int j = 0; j < x; j++){
scanf("%d", &y);
for(int k = 0; k < N; k++){
if(y == a[k]){
for(int t = 0; t < 16; t++){
printf("%c", s[k][t]);
}
printf(" %d\n",b[k]);
break;
}
}
}
return 0;
}
scanf("%s %d %d", &s[i], &a[i], &b[i]); 这里注意是%s, 第一次提交因为弄错成了%c而导致错误。
答案2
map方式
#include <iostream>
#include <map>
#include <string>
#include <cstdio>
using namespace std;
struct node{
string sno;
int num;
}stu;
map<int, node> mp;
int main(){
int t;
cin>>t;
int k = 0;
while(t--){
cin>>stu.sno;
scanf("%d %d", &k, &stu.num);
mp[k] = stu;
}
int m;
cin>>m;
for(int i = 0; i < m; i++){
int x;
cin>>x;
cout<<mp[x].sno<<" "<<mp[x].num<<endl;
}
return 0;
}
L1-006 连续因子 (20分)
一个正整数 N 的因子中可能存在若干连续的数字。例如 630 可以分解为 3×5×6×7,其中 5、6、7 就是 3 个连续的数字。给定任一正整数 N,要求编写程序求出最长连续因子的个数,并输出最小的连续因子序列。
输入格式:
输入在一行中给出一个正整数 N(1<N<231)。
输出格式:
首先在第 1 行输出最长连续因子的个数;然后在第 2 行中按 因子1*因子2*……*因子k
的格式输出最小的连续因子序列,其中因子按递增顺序输出,1 不算在内。
输入样例:
630
输出样例:
3
5*6*7
答案1
暴力解法
N<23, 因此N介于12的阶乘和13的阶乘之间,所以我们可以得到的最大的数就是12个连续的数相乘,即12的阶乘。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
int main()
{
int N;
scanf("%d", &N);
int n = sqrt(N);
int j;
long long int sum;
for(int len = 11; len > 0; len--){ //长度从11递减,因为1不算,最多只有11个数相乘
for(int i = 2; i <= n; i++){ //i > sqrt(N)时,sum
sum = 1;
for(j = i; j < len + i; j++){ //共乘len次,j的个数为len个
sum *= j;
if(sum > N) //sum > N时,没有必要继续乘下去
break;
}
if(N % sum == 0){
printf("%d\n%d", len, i); //sum从i开始乘,一直乘到j
for(int k = i + 1; k < j; k++)
printf("*%d", k);
printf("\n");
return 0;
}
}
}
printf("1\n%d\n",N); //当N是质数时,由于1不算在内,故只有一个因子是其本身
return 0;
}
第一次因少了一个return 0, 导致输出了所有可能位数和结果
第二次提交由于for(int i = 2; i <= n; i++) 写成了for(int i = 2; i < n; i++)有错误答案,未全部通过
第三次提交,发现未考虑质数而有一个测试点未通过
答案2
用了cout cin输入输出,并且利用count记录长度,更改了一下判断方法
#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
int main(){
int N, temp;
cin >> N;
int count;
int maxcount = 0;
int s = 0;
for(int i = 2; i <= sqrt(N); i++){
temp = N;
count = 0;
int j = i;
while(temp % j == 0){
temp /= j++;
count++;
}
if(count > maxcount){
maxcount = count;
s = i;
}
}
if(maxcount){
cout << maxcount << endl;
for(int i = 0; i < maxcount; i++){
cout << s+i;
if(i != maxcount - 1)
cout << "*";
}
}
else
cout << "1" <<endl << N;
return 0;
}
L1-007 念数字 (10分)
输入一个整数,输出每个数字对应的拼音。当整数为负数时,先输出fu
字。十个数字对应的拼音如下:
0: ling
1: yi
2: er
3: san
4: si
5: wu
6: liu
7: qi
8: ba
9: jiu
输入格式:
输入在一行中给出一个整数,如:1234
。
提示:整数包括负数、零和正数。
输出格式:
在一行中输出这个整数对应的拼音,每个数字的拼音之间用空格分开,行末没有最后的空格。如 yi er san si
。
输入样例:
-600
输出样例:
fu liu ling ling
答案1
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
char s[10][5] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"};
int maxn = 1010;
int main()
{
char n[maxn];
int i = 0;
while(cin>>n){
if(n[i] == '-'){
printf("fu");
i++;
}
int len = strlen(n);
if(i == 1){ //是负数
while((len - 1) != 0){
printf(" %s",s[n[i]-'0']);
len--;
i++;
}
}
else{ //不是负数
while((len - 1) != 0){
printf("%s ",s[n[i]-'0']);
len--;
i++;
}
printf("%s",s[n[i]-'0']);
}
}
return 0;
}
犯困,判断过程有些复杂了,可以考虑函数式编程,但是空格的处理似乎也还是麻烦呢
答案2
更简单的方法
#include <iostream>
using namespace std;
int main(){
string c[10] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"};
//不设数组, 直接用string输入字符串
string s;
cin>>s;
int len = s.length(); //or strlen()
int fu = s[0] == '-' ? 1 : 0;
if(fu)
cout << "fu";
for(int i = fu; i < len; i++){ //这里i= fu,根据上一步fu直接给i赋值,比答案1更简单
if(i == 0){
cout << c[s[i]-'0'];
continue;
}
cout << " " << c[s[i]-'0'];
}
return 0;
}
L1-008 求整数段和 (10分)
给定两个整数A和B,输出从A到B的所有整数以及这些数的和。
输入格式:
输入在一行中给出2个整数A和B,其中 ,其间以空格分隔。
输出格式:
首先顺序输出从A到B的所有整数,每5个数字占一行,每个数字占5个字符宽度,向右对齐。最后在一行中按Sum = X
的格式输出全部数字的和X
。
输入样例:
-3 8
输出样例:
-3 -2 -1 0 1
2 3 4 5 6
7 8
Sum = 30
答案1
格式错误,可我怎么找不出哪里错误呢???
这个解答是错误的
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int n, m;
scanf("%d %d", &n, &m);
if(n > m){ //这里是废话
int temp = n;
n = m;
m = temp;
}
int sum = 0;
int count = 0;
for(int i = 0; i <= (m - n); i++){
printf("%5d", n+i );
sum += (n + i);
count++;
if(!(count % 5)){
printf("\n");
}
else if((count % 5) && ((n + i) != m)){ //所以这个判断是错误的
printf(" ");
}
}
if(count % 5)
printf("\n");
printf("Sum = %d", sum);
return 0;
}
刚刚发现,不需要判断n, m 大小,题目给了大小关系
我换一下方式吧
aaaaa 原来%5d之后就不用加空格了!亏我还各种判断,还以为最只有最后一位才没有空格!
答案2
精简版,去掉了答案1的废话和错误的判断,用了cin和cout
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int main(){
int i, j, m, n;
cin >> m >> n;
int count = 0;
int sum = 0;
for(i = m; i <= n; i++){
count++;
sum += i;
printf("%5d", i);
if(count % 5 == 0 && i != n)
printf("\n");
}
cout << endl;
cout << "Sum = " << sum << endl;
return 0;
}
L1-009 N个数求和 (20分)
本题的要求很简单,就是求N
个数字的和。麻烦的是,这些数字是以有理数分子/分母
的形式给出的,你输出的和也必须是有理数的形式。
输入格式:
输入第一行给出一个正整数N
(≤100)。随后一行按格式a1/b1 a2/b2 ...
给出N
个有理数。题目保证所有分子和分母都在长整型范围内。另外,负数的符号一定出现在分子前面。
输出格式:
输出上述数字和的最简形式 —— 即将结果写成整数部分 分数部分
,其中分数部分写成分子/分母
,要求分子小于分母,且它们没有公因子。如果结果的整数部分为0,则只输出分数部分。
输入样例1:
5
2/5 4/15 1/30 -2/60 8/3
输出样例1:
3 1/3
输入样例2:
2
4/3 2/3
输出样例2:
2
输入样例3:
3
1/3 -1/6 1/8
输出样例3:
7/24
最小公倍数和最大公约数求法
//最小公倍数=两整数的乘积÷最大公约数
//辗转相除法
/*
1. a % b 得余数 c
2. if c == 0, 则 b 为最大公约数
3. if c != 0, 则 a = b, b = c 继续执行 1.
*/
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int m, n, a, b, c;
printf("Input two integer numbers:\n");
scanf("%d%d", &a, &b);
m = a;
n = b;
while(b != 0){
c = a % b;
a = b;
b = c;
}
printf("%d\n", a); //最大公约数
printf("%d\n", m*n/a); //最小公倍数
return 0;
}
//简写
int gcd(int a, int b){
if(b == 0)
return a;
return gcd(b, a % b);
}
//枚举法
int gcd = 1;
for(int k = 2; k <= a && k <= b; k++){
if(a % k == 0 && b % k == 0)
gcd = k;
}
//加减法
/*
1. 若a>b,则a=a-b
2. 若a < b,则b=b-a
3. 若a=b,则a(或b)即为两数的最大公约数
4. 若a≠b,则再回去执行1
*/
#include<stdio.h>
int main ( ) /* 相减法求最大公约数 */
{
int m, n, a, b, c;
printf("Input two integer numbers:\n");
scanf ("%d,%d", &a, &b);
m=a;
n=b;
while ( a!=b)
if (a>b)
a=a-b;
else
b=b-a;
printf("%d\n", a); //最大公约数
printf("%d\n", m*n/a); //最小公倍数
}
答案1
#include <iostream>
#include <stdio.h>
using namespace std;
long long gcd(long long x, long long y){
if(x == 0)
return 0;
else return (y == 0)? x : gcd(y, x%y);
}
int main()
{
int n;
scanf("%d", &n);
long long a, b, c, d;
scanf("%lld/%lld", &a, &b);
int t = gcd(a, b);
if(t){
//先给输入的分数约分一下
a /= t;
b /= t;
}
int i = 1; //已经输入了一个分数了,故i从1开始
while(i < n){
scanf("%lld/%lld", &c, &d);
long long lcp = b * d/gcd(b, d); //分母的最小公倍数
a = a * lcp / b + c * lcp / d;
b = lcp;
t = gcd(a, b); //一边加一边约分
if(t){
a /= t;
b /= t;
}
i++;
}
if(a && a / b == 0) //真分数
printf("%lld/%lld\n", a%b, b);
else if(!(a % b)) //整数
printf("%lld\n", a/b);
else
printf("%lld %lld/%lld\n", a / b, a % b, b);
return 0;
}
答案2
结构体的方法
#include <iostream>
#include <algorithm>
using namespace std;
struct node{
long long fz;
long long fm;
}frac[110];
int main(){
int n;
cin >> n;
char c; //存输入的“/”号
int sum = 1;
int s = 0; //总的分子的和
for(int i = 0; i < n; i++){
cin >> frac[i].fz >> c >> frac[i].fm;
sum *= frac[i].fm; //公共分母, 不知道会不会出现特别大的分母,看看能不能通过,再说
}
for(int i = 0; i < n; i++){
int num = frac[i].fz;
for(int j = 0; j < n; j++){
if(i != j) //用分子去乘其他所有的分母
num *= frac[j].fm;
}
s += num;
}
if(s == 0) //0
cout << "0" << endl;
else if(s % sum == 0) //整数
cout << s/sum << endl;
else{
if(s / sum >= 1){ //假分数
int a = s / sum;
s %= sum;
int gcd = __gcd(s, sum);
cout << a << " " << s / gcd << "/" << sum / gcd << endl;
//这里用scanf好了,cout有点麻烦,同除gcd约分
}
else{
int gcd = __gcd(s, sum);
cout << s / gcd << "/" << sum / gcd << endl;
}
}
return 0;
}
用了内置的__gcd()函数 #algorithm
L1-010 比较大小 (10分)
本题要求将输入的任意3个整数从小到大输出。
输入格式:
输入在一行中给出3个整数,其间以空格分隔。
输出格式:
在一行中将3个整数从小到大输出,其间以“->”相连。
输入样例:
4 2 8
输出样例:
2->4->8
答案
#include <iostream>
#include <algorithm>
#include <math.h>
#include <stdio.h>
using namespace std;
int main()
{
int a, b, c;
cin >> a >> b >> c;
int x = max(max(a,b),max(b,c));
if(x == b){
b = a;
a = x;
}else if(x == c){
c = a;
a = x;
}
int y = max(b, c);
if(y == c){
c = b;
b = y;
}
printf("%d->%d->%d", c, b, a);
return 0;
}
或许可能上述判断过程复杂了点,不过似乎也没复杂到哪里去emm就这样
总看错题哎,以为从大到小的顺序,用了max(), 还好后面输出把a , c 换一下位置就好
NEXT
L1-011 A-B (20分)
本题要求你计算 A−B。不过麻烦的是,A 和 B 都是字符串 —— 即从字符串 A 中把字符串 B 所包含的字符全删掉,剩下的字符组成的就是字符串 A−B。
输入格式:
输入在2行中先后给出字符串 A 和 B 。两字符串的长度都不超过104,并且保证每个字符串都是由可见的ASCII码和空白字符组成,最后以换行符结束。
输出格式:
在一行中打印出 A−B 的结果字符串。
输入样例:
I love GPLT! It's a fun game!
aeiou
输出样例:
I lv GPLT! It's fn gm!
答案
对B中出现的字符进行标记,输出无标记的即可
#include <iostream>
#include <stdio.h>
using namespace std;
int maxn = 10010;
int main()
{
char s[maxn], c;
int a[256] = {0};
int i = 0;
fgets(s, maxn, stdin); //gets(s); 这个用不了
while((c = getchar())!= '\n')
a[c] = 1;
while(s[i] != 0)
{
if(!a[s[i]])
putchar(s[i]);
i++;
}
//cout << endl; 不可以换行 会格式错误
return 0;
}
L1-012 计算指数 (5分)
真的没骗你,这道才是简单题 —— 对任意给定的不超过 10 的正整数 n,要求你输出 2n。不难吧?
输入格式:
输入在一行中给出一个不超过 10 的正整数 n。
输出格式:
在一行中按照格式 2^n = 计算结果
输出 2n 的值。
输入样例:
5
输出样例:
2^5 = 32
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int n;
cin >> n;
int sum = 1;
for(int i = 0; i < n; i++){
sum *= 2;
}
printf("2^%d = %d", n, sum);
return 0;
}
L1-013 计算阶乘和 (10分)
对于给定的正整数 ,需要你计算
输入格式:
输入在一行中给出一个不超过10的正整数 N。
输出格式:
在一行中输出S的值。
输入样例:
3
输出样例:
9
答案
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int n;
cin >> n;
int sum = n;
for(int i = n-1; i >= 1; i--){
sum = ( i *(1 + sum));
}
cout << sum << endl;
return 0;
}
L1-014 简单题 (5分)
这次真的没骗你 —— 这道超级简单的题目没有任何输入。
你只需要在一行中输出事实:This is a simple problem.
就可以了。
输入样例:
无
输出样例:
This is a simple problem.
答案
#include <iostream>
using namespace std;
int main()
{
cout << "This is a simple problem." << endl;
return 0;
}
L1-015 跟奥巴马一起画方块 (15分)
美国总统奥巴马不仅呼吁所有人都学习编程,甚至以身作则编写代码,成为美国历史上首位编写计算机代码的总统。2014年底,为庆祝“计算机科学教育周”正式启动,奥巴马编写了很简单的计算机代码:在屏幕上画一个正方形。现在你也跟他一起画吧!
输入格式:
输入在一行中给出正方形边长N(3≤N≤21)和组成正方形边的某种字符C
,间隔一个空格。
输出格式:
输出由给定字符C
画出的正方形。但是注意到行间距比列间距大,所以为了让结果看上去更像正方形,我们输出的行数实际上是列数的50%(四舍五入取整)。
输入样例:
10 a
输出样例:
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
答案
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int n;
char c;
scanf("%d %c", &n, &c);
int N = n;
if(n % 2)
N = n + 1;
for(int i = 0; i < N/2; i++){
for(int j = 0; j < n; j++){
printf("%c", c);
}
if(i != N/2-1)
printf("\n");
}
return 0;
}
L1-016 查验身份证 (15分)
一个合法的身份证号码由17位地区、日期编号和顺序编号加1位校验码组成。校验码的计算规则如下:
首先对前17位数字加权求和,权重分配为:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};然后将计算的和对11取模得到值Z
;最后按照以下关系对应Z
值与校验码M
的值:
Z:0 1 2 3 4 5 6 7 8 9 10
M:1 0 X 9 8 7 6 5 4 3 2
现在给定一些身份证号码,请你验证校验码的有效性,并输出有问题的号码。
输入格式:
输入第一行给出正整数N(≤100)是输入的身份证号码的个数。随后N行,每行给出1个18位身份证号码。
输出格式:
按照输入的顺序每行输出1个有问题的身份证号码。这里并不检验前17位是否合理,只检查前17位是否全为数字且最后1位校验码计算准确。如果所有号码都正常,则输出All passed
。
输入样例1:
4
320124198808240056
12010X198901011234
110108196711301866
37070419881216001X
输出样例1:
12010X198901011234
110108196711301866
37070419881216001X
输入样例2:
2
320124198808240056
110108196711301862
输出样例2:
All passed
答案1
#include <iostream>
#include <stdio.h>
#include <sstream>
#include <string>
using namespace std;
int main(){
int n;
cin >> n;
char m[11] = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
int q[17] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
int sum = 0;
string id;
int x = n;
while(n--){
int flag = 0; //注意这个flag要设在while循环内
cin >> id;
for(int i = 0; i < 17; i++){
if(id[i] < '0' || id[i] > '9'){
cout << id << endl;
flag = 1;
break;
}
}
int s = 0;
if(!flag){
for(int i = 0; i < 17; i++){
int p;
stringstream convert;
convert << id[i];
convert >> p;
s += p*q[i];
}
s %= 11;
if(m[s] == id[17])
sum ++; //记录通过数
else
cout << id << endl;
}
}
if(sum == x)
cout << "All passed" << endl;
return 0;
}
stringstream
stringstream 是 中定义的类,流的输入输出操作。
主要用来进行数据类型转换
int 转化为string
#include <string>
#include <sstream>
#include <iostream>
#include <stdio.h>
using namespace std;
int main(){
stringstream convert;
string str;
int n = 1234;
convert << n; //int 类型放入输入流中
convert >> str; //赋给string类型
cout << str << endl;
prinf("%s\n", str.c_str());
return 0;
}
字符串拼接
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
int main(){
stringstream convert;
convert << "abc";
convert << "opq"; //拼接后
cout << convert.str() << endl; //str方法将stringstream类型转化为string类型
convert.str(""); //清空
convert << "xyz";
cout << convert.str() << endl; //清空后重新赋
return 0;
}
答案2
这个答案来源于网上,不过找不到是哪位写的了QAQ
#include <iostream>
#include <string>
using namespace std;
bool func(string s){
int sum = 0;
int a[18];
for(int i = 0; i < 17; i++){
if(!isdigit(s[i])){ //isdigit是计算机C(C++)语言中的一个函数,主要用于检查其参数是否为十进制数字字符。
cout << s << endl;
return true; //这里原代码写的是 return false, 我怎么觉得应该是true? 但是不管是true or false 都通过了测试点...
}
a[i] = s[i] - '0';
}
if(s[17] == 'X')
a[17] = 10;
else
a[17] = s[17] - '0';
int b[17] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
for(int i = 0; i < 17; i++){
sum += a[i]*b[i]; //原代码是sum = sum +, 用 += 更简洁
}
sum %= 11;
int c[11] = {1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2};
if(c[sum] != a[17]){
for(int i = 0; i < 17; i++){
cout << s[i];
}
if(a[17] != 10)
cout << a[17] << endl;
else{
cout << "X" << endl;
}
return true;
}
else{
return false;
}
}
int main(){
int n;
int count = 0;
cin >> n;
for(int i = 0; i < n; i++){
string a;
cin >> a;
if(func(a))
count ++;
}
if(count == 0)
cout << "All passed";
return 0;
}
L1-017 到底有多二 (15分)
一个整数“犯二的程度”定义为该数字中包含2的个数与其位数的比值。如果这个数是负数,则程度增加0.5倍;如果还是个偶数,则再增加1倍。例如数字-13142223336
是个11位数,其中有3个2,并且是负数,也是偶数,则它的犯二程度计算为:3/11×1.5×2×100%,约为81.82%。本题就请你计算一个给定整数到底有多二。
输入格式:
输入第一行给出一个不超过50位的整数N
。
输出格式:
在一行中输出N
犯二的程度,保留小数点后两位。
输入样例:
-13142223336
输出样例:
81.82%
答案
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
int main()
{
char str[55];
cin >> str;
//printf("%c", str[3]);
double h = 1;
int a = 0, b = 0; //a表示总长度, b表示2的个数
if(str[0] == '-'){ //是否是负数
h *= 1.5;
a = strlen(str) - 1;
}
else{
a = strlen(str);
}
if((str[strlen(str)-1] - '0')%2 == 0) //只需看最后一位是否是偶数
h *= 2;
for(int i = 0; i < strlen(str); i++){
if(str[i] == '2'){
b++;
}
}
double sum = h * b * 1.0 / a * 100; //注意转化为浮点数
printf("%.2f%%\n", sum); //转义
return 0;
}
L1-018 大笨钟 (10分)
微博上有个自称“大笨钟V”的家伙,每天敲钟催促码农们爱惜身体早点睡觉。不过由于笨钟自己作息也不是很规律,所以敲钟并不定时。一般敲钟的点数是根据敲钟时间而定的,如果正好在某个整点敲,那么“当”数就等于那个整点数;如果过了整点,就敲下一个整点数。另外,虽然一天有24小时,钟却是只在后半天敲1~12下。例如在23:00敲钟,就是“当当当当当当当当当当当”,而到了23:01就会是“当当当当当当当当当当当当”。在午夜00:00到中午12:00期间(端点时间包括在内),笨钟是不敲的。
下面就请你写个程序,根据当前时间替大笨钟敲钟。
输入格式:
输入第一行按照hh:mm
的格式给出当前时间。其中hh
是小时,在00到23之间;mm
是分钟,在00到59之间。
输出格式:
根据当前时间替大笨钟敲钟,即在一行中输出相应数量个Dang
。如果不是敲钟期,则输出:
Only hh:mm. Too early to Dang.
其中hh:mm
是输入的时间。
输入样例1:
19:05
输出样例1:
DangDangDangDangDangDangDangDang
输入样例2:
07:05
输出样例2:
Only 07:05. Too early to Dang.
答案
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int hh, mm;
scanf("%d:%d", &hh, &mm);
if(hh < 12 || (hh == 12 && mm == 00)){
printf("Only %02d:%02d. Too early to Dang.", hh, mm);
}
else{
if(mm){
for(int i = 0; i <= hh - 12; i++){
printf("Dang");
}
}
else{
for(int i = 0; i < hh - 12; i++){
printf("Dang");
}
}
}
return 0;
}
CS 61A 函数式编程
void print(int hh){ for(int i = 0; i < hh - 12; i++){ printf("Dang"); } } print(hh); print(hh + 1);
L1-019 谁先倒 (15分)
划拳是古老中国酒文化的一个有趣的组成部分。酒桌上两人划拳的方法为:每人口中喊出一个数字,同时用手比划出一个数字。如果谁比划出的数字正好等于两人喊出的数字之和,谁就输了,输家罚一杯酒。两人同赢或两人同输则继续下一轮,直到唯一的赢家出现。
下面给出甲、乙两人的酒量(最多能喝多少杯不倒)和划拳记录,请你判断两个人谁先倒。
输入格式:
输入第一行先后给出甲、乙两人的酒量(不超过100的非负整数),以空格分隔。下一行给出一个正整数N
(≤100),随后N
行,每行给出一轮划拳的记录,格式为:
甲喊 甲划 乙喊 乙划
其中喊
是喊出的数字,划
是划出的数字,均为不超过100的正整数(两只手一起划)。
输出格式:
在第一行中输出先倒下的那个人:A
代表甲,B
代表乙。第二行中输出没倒的那个人喝了多少杯。题目保证有一个人倒下。注意程序处理到有人倒下就终止,后面的数据不必处理。
输入样例:
1 1
6
8 10 9 12
5 10 5 10
3 8 5 12
12 18 1 13
4 16 12 15
15 1 1 16
输出样例:
A
1
答案
#include <iostream>
using namespace std;
int main()
{
int ja, jb;
cin >> ja >> jb;
int a = ja, b = jb;
int n;
cin >> n;
for(int i = 0; i < n; i++){
int ha, hb, hua, hub;
cin >> ha >> hua >> hb >> hub;
if(hua == (ha + hb) && hub == (ha + hb)) //第一次提交忘记了判断两人同输的情况
continue;
else{
if(hua == (ha + hb))
ja--;
if(hub == (ha + hb))
jb--;
if(ja < 0){ //第二次发现这里不是 == 0 而是 < 0 才算喝醉 (′⌒`)
cout << "A" << endl << b - jb;
return 0;
}
else if(jb < 0){
cout << "B" << endl << a - ja;
return 0;
}
}
}
return 0;
}
L1-020 帅到没朋友 (20分)
当芸芸众生忙着在朋友圈中发照片的时候,总有一些人因为太帅而没有朋友。本题就要求你找出那些帅到没有朋友的人。
输入格式:
输入第一行给出一个正整数N
(≤100),是已知朋友圈的个数;随后N
行,每行首先给出一个正整数K
(≤1000),为朋友圈中的人数,然后列出一个朋友圈内的所有人——为方便起见,每人对应一个ID号,为5位数字(从00000到99999),ID间以空格分隔;之后给出一个正整数M
(≤10000),为待查询的人数;随后一行中列出M
个待查询的ID,以空格分隔。
注意:没有朋友的人可以是根本没安装“朋友圈”,也可以是只有自己一个人在朋友圈的人。虽然有个别自恋狂会自己把自己反复加进朋友圈,但题目保证所有K
超过1的朋友圈里都至少有2个不同的人。
输出格式:
按输入的顺序输出那些帅到没朋友的人。ID间用1个空格分隔,行的首尾不得有多余空格。如果没有人太帅,则输出No one is handsome
。
注意:同一个人可以被查询多次,但只输出一次。
输入样例1:
3
3 11111 22222 55555
2 33333 44444
4 55555 66666 99999 77777
8
55555 44444 10000 88888 22222 11111 23333 88888
输出样例1:
10000 88888 23333
输入样例2:
3
3 11111 22222 55555
2 33333 44444
4 55555 66666 99999 77777
4
55555 44444 22222 11111
输出样例2:
No one is handsome
答案
#include <iostream>
#include <stdio.h>
using namespace std;
int id[100010] = {0};
//int flag[100010] = {0}; 没用上
int main()
{
int n;
cin >> n;
for(int i = 0; i < n; i++){
int m;
cin >> m; //*
for(int j = 0; j < m; j++){
int i;
cin >> i;
if(m != 1) //第一次忘记判断m是否等于1, 第二次将 m != 1放在了*位置,导致输入错误了
id[i] = 1;
}
}
int c;
int count = 0;
cin >> c;
for(int i = 0; i < c; i++){
int x;
cin >> x;
if(id[x] != 1){
id[x] = 1; //&
if(count == 0)
printf("%05d", x); //第一次空格输入不对, 第二次数字格式错误了
//cout << x ;
else
printf(" %05d", x);
//cout << " " << x;
count++; //还有一次把count++放在了&这里,出错了qaq
}
}
if(!count)
cout << "No one is handsome" ;
return 0;
}
这个答案最后一个测试点用了80ms,而AC的答案里有20ms以内的,分析原因,其实是cin和scanf, cout 和 printf 的速度问题,cin 和cout 普遍慢于 scanf 和 printf。(这题能看出来真的慢了好多啊…)
害,改了N遍,咸鱼一条,基础先做到这里,赶快捡起我的数据结构吧,树图马上就忘光了…