写在前面:
PAT冬季赛马上就要开始了!这一次先报一个乙级冲鸭!我感Jio乙级里面还是有蛮多水题的,也有些题虽然看上去是水题,但是真正用代码实现起来的话会卡你那么一下。
今天才开始刷的乙级真题,前段时间妄想暴富沉迷赌球,现在很后悔变成输几个的老哥。天上不会掉馅饼的,好好学习,努力奋斗才能梦想成真。十四天速成PAT乙级,冲鸭!!!
1. D进制的A + B(20 分)
题目描述:
输入两个非负10进制整数A和B(<= 230-1),输出A + B的D(1 <D <= 10)进制数。
输入格式:
输入在一行中依次给出3个整数A,B和D。
输出格式:
输出A + B的D进制数。
输入样例:
123 456 8
输出样例:
1103
解题思路:
首先,这道题看上去很简单,但是用代码实现起来发现有点难受啊。幸亏数据结构没白学,我用了一个堆栈。先令C = A + B如果C等于0,就直接输出0,否则对C进行进制转换。这道题主要考察的应该就是将十进制的C转换成D进制。先把C对D的余数推入栈中,然后C除以D的值赋给C,最后根据堆栈“后进先出”的规则输出C对D的余数,也就得到了D进制下的C。
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 int main()
5 {
6 int a,b,d;
7 cin >> a >> b >> d;
8 stack<int> s;
9 int c = a+b;
10 if(c == 0)
11 {
12 cout << 0;
13 }
14 while(c!=0)
15 {
16 s.push(c%d);
17 c /= d;
18 }
19 while(!s.empty())
20 {
21 cout << s.top();
22 s.pop();
23 }
24 return 0;
25 }
2. A + B和C(15 分)
题目描述:
给定区间[-2的31次方,2的31次方]内的3个整数A,B和C,请判断A + B是否大于C。
输入格式:
输入第1行给出正整数T(<= 10),是测试用例的个数。随后给出Ť组测试用例,每组占一行,顺序给出A,B和C.整数间以空格分隔。
输出格式:
对每组测试用例,在一行中输出“Case #X:true”如果A + B> C,否则输出“Case #X:false”,其中X是测试用例的编号(从1开始)。
输入样例:
4
1 2 3
2 3 4
2147483647 0 2147483646
0 -2147483648 -2147483647
输出样例:
Case #1: false
Case #2: true
Case #3: true
Case #4: false
解题思路:
首先看到这道题给定的区间是[-2的31次方,2的31次方],直接无脑用Python的。这段代码中最秀的地方就是这个a,b,c=map(int,input().split())啦!map()函数的用法如下:map(func,[seq1,seq2,...])第一个参数接受一个函数名,后面的参数接受一个或多个可Python的函数编程中的map()函数是将FUNC作用于SEQ中的每一个元素,并将所有的调用的结果作为一个列表返回。
AC代码:
1 t = eval(input())
2 for i in range(1,t+1):
3 a,b,c=map(int,input().split())
4 if a+b>c:
5 print("Case #{}: true".format(i))
6 else:
7 print("Case #{}: false".format(i))
3.查验身份证(15 分)
题目描述:
一个合法的身份证号码由17位地区,日期编号和顺序编号加1位校验码组成校验码的计算规则如下:
首先对前17位数字加权求和,权重分配为:{7,9, 10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};然后将计算的和对11取模得到值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”。
输入样例:
4
320124198808240056
12010X198901011234
110108196711301866
37070419881216001X
输出样例:
12010X198901011234
110108196711301866
37070419881216001X
解题思路:
首先,这个题目看起我有点懵逼,真的题目都看了3,4遍。好好缕了下思路之后,先建立俩个数组分别用来存放权值分配和校验码M.然后取消cin与stdin的同步压压惊,真的怕TLE,毕竟要对若干个18位数的身份证每一位进行校验。立个flag=true,如果到最后,标志还是为true,表明所有的身份证号码都正常,输出“All passed”。然后isTrue用来判断每一个身份证号的前17位是否全为数字,若不是数字则isTrue和flag都变成false,用sum来计算身份证号号的每一位数和它所占的权值的乘积之和,将计算出来的总和对11取模得到值Z,根据题意可知,可以根据z值来找到对应的校验码中号的值,若IsTrue运算为真但校验码中号和身份证最后一位不相等,这个身份证号也是错误的,需要对错误的身份证号进行输出。
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 int weight[17] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
5 char M[11] = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
6
7 int main()
8 {
9 ios::sync_with_stdio(false);
10 int n;
11 cin >> n;
12 string ID;
13 bool flag = true;
14 for (int i = 0; i < n; i++)
15 {
16 int sum = 0;
17 bool isTrue = true;
18 cin >> ID;
19 for(int j = 0; j < 17; j++)
20 {
21 if(ID[j]<'0'||ID[j]>'9')
22 {
23 cout << ID << endl;
24 flag = false;
25 isTrue = false;
26 break;
27 }
28 sum += (ID[j]-'0')*weight[j];
29 }
30 int z = sum%11;
31 if(ID[17]!=M[z] && isTrue)
32 {
33 flag = false;
34 cout << ID << endl;
35 }
36 }
37 if(flag)
38 {
39 cout << "All passed" << endl;
40 }
41 return 0;
42 }
4.数字分类(20 分)
题目描述:
给定一系列正整数,请按要求对数字进行分类,并输出以下5个数字:
A1 = 能被5整除的数字中所有偶数的和;
A2 = 将被5除后余1的数字按给出顺序进行交错求和,即计算n1-n2+n3-n4...;
A3 = 被5除后余2的数字的个数;
A4 = 被5除后余3的数字的平均数,精确到小数点后1位;
A5 = 被5除后余4的数字中最大数字。
输入格式:
每个输入包含1个测试用例。每个测试用例先给出一个不超过1000的正整数N,随后给出N个不超过1000的待分类的正整数。数字间以空格分隔。
输出格式:
对给定的N个正整数,按题目要求计算A1~A5并在一行中顺序输出。数字间以空格分隔,但行末不得有多余空格。
若其中某一类数字不存在,则在相应位置输出'N'。
输入样例:
13 1 2 3 4 5 6 7 8 9 10 20 16 18
输出样例:
30 11 2 9.7 9
解题思路:
首先,根据题意可知这是一道水题,真的水得不能再水了,直接按着题目来就求A1,A2,A3,A4,A5就行啦,整除5的时候可以用switch,但是我用的的if-else。
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 int main()
5 {
6 int n;
7 cin >> n;
8 int a[n];
9 for (int i = 0; i < n; i++)
10 {
11 cin >> a[i];
12 }
13 int A1 = 0,A2 = 0,A3 = 0,A5 = -1e5,count_A4 = 0;
14 double A4;
15 int flag = 1;
16 bool T1 = false,T2 = false,T3 = false,T4 = false,T5 = false;
17 for (int i = 0; i < n; i++)
18 {
19 if(a[i]%5==0 && a[i]%2==0) //A1是能被5整除的所有偶数的和
20 {
21 A1 += a[i];
22 T1 = true;
23 }
24 if(a[i]%5==1) //A2是将被5除后余1的数字按给出顺序进行交错求和
25 {
26 A2 += a[i]*flag;
27 flag = -flag;
28 T2 = true;
29 }
30 if(a[i]%5==2) //A3是被5除后余2的数字的个数
31 {
32 A3++;
33 T3 = true;
34 }
35 if(a[i]%5==3) //A4是被5除后余3的数字的平均数,精确到小数点后1位
36 {
37 A4 += a[i];
38 count_A4++;
39 T4 = true;
40 }
41 if(a[i]%5==4) //A5是被5除后余4的数字中最大数字
42 {
43 if(a[i] > A5)
44 {
45 A5 = a[i];
46 }
47 T5 = true;
48 }
49 }
50 if(T1)
51 {
52 cout << A1 << " ";
53 }
54 else
55 {
56 cout << 'N' << " ";
57 }
58 if(T2)
59 {
60 cout << A2 << " ";
61 }
62 else
63 {
64 cout << 'N' << " ";
65 }
66 if(T3)
67 {
68 cout << A3 << " ";
69 }
70 else
71 {
72 cout << 'N' << " ";
73 }
74 if(T4)
75 {
76 printf("%.1lf ",A4/count_A4);
77 }
78 else
79 {
80 cout << 'N' << " ";
81 }
82 if(T5)
83 {
84 cout << A5 << endl;
85 }
86 else
87 {
88 cout << 'N' << endl;
89 }
90 return 0;
91 }
5.数素数(20 分)
题目描述:
令Pi表示第i个素数。现任给两个正整数M <= N <= 10000,请输出PM到PN的所有素数。
输入格式:
输入在一行中给出M和N,其间以空格分隔。
输出格式:
输出从PM到PN的所有素数,每10个数字占1行,其间以空格分隔,但行末不得有多余空格。
输入样例:
5 27
输出样例:
11 13 17 19 23 29 31 37 41 43
47 53 59 61 67 71 73 79 83 89
97 101 103
解题思路:
首先根据题意可知这是一道水题,不就是建立一个求素数的函数,然后用for循环对第m个素数到第n个素数进行输出吗?(尴尬地划掉第一句话,有个测试用例错误打我脸了)当输入10000 10000这个测试用例时,我写的第一个算法有bug,它会直接输出0,而第10000个素数是104729,这才是期待的输出。我把10000改成110000,int改成long long型也无济于事,懵逼了。与其花费时间去修改这个bug,不如推翻重来换一个思路,然后我写了一种用优先队列的算法,测试用例全部AC,哈哈哈哈 数据结构还是没白学。首先自定义一个isPrime(int n)的函数用来判断一个数是否为素数,然后再主函数中用count来记录素数的个数,当count在[m,n]这个范围内时,对这个素数进行入队操作。为了输出格式和题目要求相符,先立一个flag,第m个素数一输出就把flag改掉,然后先输出空格再输出素数,这样就可以避免最后的第n个素数后面还出现空格而导致格式错误的情况。
AC代码:打脸代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 bool isPrime(int n)
5 {
6 for(int i=2;i<=sqrt(n);i++)
7 {
8 if(n%i==0)
9 {
10 return false;
11 }
12 }
13 return true;
14 }
15
16 int main()
17 {
18 int m,n;
19 cin >> m >> n;
20 int a[10000];
21 for(int i=1, j=0;i<=10000;i++)
22 {
23 if(isPrime(i))
24 {
25 a[j++] = i;
26 }
27 }
28 bool flag = true;
29 int count = 0;
30 for (int i = m; i <= n; ++i)
31 {
32 if(flag)
33 {
34 cout << a[i];
35 flag = false;
36 }
37 else
38 {
39 cout << " " << a[i];
40 }
41 count++;
42 if(count%10 == 0)
43 {
44 flag = true;
45 cout << endl;
46 }
47 }
48 return 0;
49 }
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 bool isPrime(int n)
5 {
6 if(n<=1) return false;
7 for(int i=2;i<=sqrt(n);i++)
8 {
9 if(n%i==0)
10 {
11 return false;
12 }
13 }
14 return true;
15 }
16
17 int main()
18 {
19 int m,n;
20 cin >> m >> n;
21 priority_queue< int, vector<int>, greater<int> > l; //优先队列
22 int count = 0;
23 for(int i=1;count<=n;i++)
24 {
25 if(isPrime(i))
26 {
27 count++;
28 if(count>=m && count<=n)
29 {
30 l.push(i);
31 }
32 }
33 }
34 bool flag = true;
35 count = 0;
36 for (int i = m; i <= n; ++i)
37 {
38 if(flag)
39 {
40 cout << l.top();
41 l.pop();
42 flag = false;
43 }
44 else
45 {
46 cout << " " << l.top();
47 l.pop();
48 }
49 count++;
50 if(count%10 == 0)
51 {
52 flag = true;
53 cout << endl;
54 }
55 }
56 return 0;
57 }
修改后AC的打脸代码:
哈哈哈哈哈 问过老师之后 发现这段代码放了3个低级错误:①判断素数时直接忽略了1这种情况;②第一个for循环的判断部分应该是j<=`10000,因为最多是要数10000个素数,可能是因为深夜写代码写起很困的时候脑子不清醒,明明想的是j<=10000,③设置数组大小时,a应该设置比10000要大,防止数据溢出。感谢老师。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 bool isPrime(int n) 5 { 6 if(n<=1) 7 { 8 return false; 9 } 10 for(int i=2;i<=sqrt(n);i++) 11 { 12 if(n%i==0) 13 { 14 return false; 15 } 16 } 17 return true; 18 } 19 20 int main() 21 { 22 int m,n; 23 cin >> m >> n; 24 int a[10001]; 25 for(int i=1, j=1;j<=10000;i++) 26 { 27 if(isPrime(i)) 28 { 29 a[j++] = i; 30 } 31 } 32 bool flag = true; 33 int count = 0; 34 for (int i = m; i <= n; i++) 35 { 36 if(flag) 37 { 38 cout << a[i]; 39 flag = false; 40 } 41 else 42 { 43 cout << " " << a[i]; 44 } 45 count++; 46 if(count%10 == 0) 47 { 48 flag = true; 49 cout << endl; 50 } 51 } 52 return 0; 53 }
6.锤子剪刀布(20 分)
题目描述:
大家应该都会玩“锤子剪刀布”的游戏。现给出两人的交锋记录,请统计双方的胜,平,负次数,并且给出双方分别出什么手势的胜算最大。
输入格式:
输入第1行给出正整数N(<= 105),即双方交锋的次数。随后Ñ行,每行给出一次交锋的信息,即甲,乙双方同时给出的的手势.C代表“锤子“,J代表‘剪刀’,B代表‘布’,第1个字母代表甲方,第2个代表乙方,中间有1个空格。
输出格式:
输出第1,2行分别给出甲,乙的胜,平,负次数,数字间以1个空格分隔。第3行给出两个字母,分别代表甲,乙获胜次数最多的手势,中间有1个空格。如果解不唯一,则输出按字母序最小的解。
输入样例:
10
C J
J B
C B
B B
B C
C C
C B
J B
B C
J J
输出样例:
5 3 2
2 3 5
B B
解题思路:
首先通过题意可知这是一道代码量很大的水题。它不仅需要记录甲乙胜负平的次数,而且需要记录甲乙获胜的手势,然后通过比较来找出获胜最多的手势,在不唯一的情况下输出字母序最小的解。
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 char getMax(int b,int c,int j)
5 {
6 if(b!=c&&b!=j&&c!=j)
7 {
8 if(b>c&&b>j)
9 {
10 return 'B';
11 }
12 if(c>b&&c>j)
13 {
14 return 'C';
15 }
16 if(j>b&&j>c)
17 {
18 return 'J';
19 }
20 }
21 else
22 {
23 if(b==c&&b>j)
24 {
25 return 'B';
26 }
27 if(b==c&&b<j)
28 {
29 return 'J';
30 }
31 if(c==j&&c>b)
32 {
33 return 'C';
34 }
35 if(c==j&&c<b)
36 {
37 return 'B';
38 }
39 if(b==j&&b>c)
40 {
41 return 'B';
42 }
43 if(b==j&&b<c)
44 {
45 return 'C';
46 }
47 if(b==j&&c==j&&b==c)
48 {
49 return 'B';
50 }
51 }
52 return '1';
53 }
54
55 int main()
56 {
57 int n;
58 cin >> n;
59 int count_XC=0,count_XJ=0,count_XB=0;
60 int count_YC=0,count_YJ=0,count_YB=0;
61 int count_Xwin=0,count_Xlose=0,count_Xequal=0;
62 for (int i = 0; i < n; ++i)
63 {
64
65 char X,Y;
66 cin >> X >> Y;
67 if(X == Y)
68 {
69 count_Xequal++;
70 }
71 else
72 {
73 bool X_defeat_Y = false;
74 if((X=='C'&&Y=='J')||(X=='J'&&Y=='B')||(X=='B'&&Y=='C'))
75 {
76 X_defeat_Y = true;
77 }
78 if(X_defeat_Y)
79 {
80 switch(X)
81 {
82 case 'C': count_XC++; break;
83 case 'J': count_XJ++; break;
84 case 'B': count_XB++; break;
85 default : break;
86 }
87 count_Xwin++;
88 }
89 else
90 {
91 switch(Y)
92 {
93 case 'C': count_YC++; break;
94 case 'J': count_YJ++; break;
95 case 'B': count_YB++; break;
96 default : break;
97 }
98 count_Xlose++;
99 }
100 }
101 }
102 cout << count_Xwin << " " << count_Xequal << " " << count_Xlose << endl;
103 cout << count_Xlose << " " << count_Xequal << " " << count_Xwin << endl;
104 int max_X=-1e5,max_Y=-1e5;
105 char maxc_X = getMax(count_XB,count_XC,count_XJ);
106 char maxc_Y = getMax(count_YB,count_YC,count_YJ);
107 cout << maxc_X << " " << maxc_Y << endl;
108 return 0;
109 }
7.个位数统计(15 分)
题目描述:
给定一个k位整数N = dk-1 * 10k-1 + ... + d1 * 101 + d0(0 <= di <= 9,i = 0,...,k-1,dk-1> 0),请编写程序统计每种不同的个位数字出现的次数。例如:给定N = 100311,则有2个0,3个1,和1个3。
输入格式:
每个输入包含1个测试用例,即一个不超过1000位的正整数N。
输出格式:
对N中每一种不同的个位数字,以d:M的格式在一行中输出该位数字d及其在N中出现的次数M.要求按d的升序输出。
输入样例:
100311
输出样例:
0:2
1:3
3:1
解题思路:
首先,根据题意可知这是一道水题,那么问题来了,怎么在写水题的同时秀一波操作呢?额,我用一个map<char, int>来存放出现过的数字并记录下出现的次数,然后用for-each循环来对map进行遍历并输出出现过的数字和出现的次数。
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 int main()
5 {
6 string n;
7 map<char, int> m;
8 cin >> n;
9 for(auto i:n)
10 {
11 m[i]++;
12 }
13 for (auto i:m)
14 {
15 cout << i.first << ":" << i.second << endl;
16 }
17 return 0;
18 }
8.组个最小数(20 分)
题目描述:
给定数字0-9各若干个你可以以任意顺序排列这些数字,但必须全部使用目标是使得最后得到的数尽可能小(注意0不能做首位)例如:。给定两个0,两个1,三个5,一个如图8所示,我们得到的最小的数就是10015558.现给定数字,请编写程序输出能够组成的最小的数。
输入格式:
每个输入包含1个测试用例。每个测试用例在一行中给出10个非负整数,顺序表示我们拥有数字0,数字1,......数字9的个数。整数间用一个空格分隔0.10个数字的总个数不超过50,且至少拥有1个非0的数字。
输出格式:
在一行中输出能够组成的最小的数。
输入样例:
2 2 0 0 0 3 0 0 1 0
输出样例:
10015558
解题思路:
首先,根据题意可知这是一道水题,第一位数输出非0的最小值,然后后面的位数直接依次把身下的数字中的最小值输出,输出的结果就是最小数。
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3 #define n 10
4 int main()
5 {
6 int a[n];
7 for (int i = 0; i < n; i++)
8 {
9 cin >> a[i];
10 }
11 for(int i = 1; i < n; i++) //先输出第一位数
12 {
13 if(a[i])
14 {
15 cout << i;
16 a[i]--;
17 break;
18 }
19 }
20 for(int i = 0; i < n; i++)
21 {
22 while(a[i]--)
23 {
24 cout << i;
25 }
26 }
27 return 0;
28 }
9.程序运行时间(15 分)
题目描述:
要获得一个C语言程序的运行时间,常用的方法是调用头文件time.h中,其中提供了时钟()函数,可以捕捉从程序开始运行到时钟()被调用时所耗费的时间。这个时间单位是时钟滴答,即“时钟打点”。同时还有一个常数CLK_TCK,给出了机器时钟每秒所走的时钟打点数。于是为了获得一个函数f的运行时间,我们只要在调用f之前先调用时钟(),获得一个时钟打点数C1;在˚F执行完成后再调用时钟(),获得另一个时钟打点数C2;两次获得的时钟打点数之差(C2-C1)就是˚F运行所消耗的时钟打点数,再除以常数CLK_TCK,就得到了以秒为单位的运行时间。
这里不妨简单假设常数CLK_TCK为100现给定被测函数前后两次获得的时钟打点数,请你给出被测函数运行的时间。
输入格式:
输入在一行中顺序给出2个整数C1和C1。注意两次获得的时钟打点数肯定不相同,即C1 <C2,并且取值在[0,107]
输出格式:
在一行中输出被测函数运行的时间。运行时间必须按照“hh:mm:ss”(即2位的“时:分:秒”)格式输出;不足1秒的时间四舍五入到秒。
输入样例:
123 4577973
输出样例:
12:42:59
解题思路:
首先,根据题意可知这是一道水题,真的水得不能再水了,直接求出C1和C2的时间差,然后化成时分秒就行了。
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 int main()
5 {
6 int c1,c2;
7 cin >> c1 >> c2;
8 int t = round((c2-c1)/100.0);
9 printf("%02d:%02d:%02d
",t/3600,t%3600/60,t%60);
10 return 0;
11 }
10.人口普查(20 分)
题目描述:
某城镇进行人口普查,得到了全体居民的生日。现请你写个程序,找出镇上最年长和最年轻的人。这里确保每个输入的日期都是合法的,但不一定是合理的-假设已知镇上没有超过200岁的老人,而今天是2014年9月6日,所以超过200岁的生日和未出生的生日都是不合理的,应该被过滤掉。
输入格式:
输入在第一行给出正整数N,取值在(0,105);随后N行,每行给出1个人的姓名(由不超过5个英文字母组成的字符串),以及 按“yyyy / MM / DD”(即年/月/日)格式给出的生日。题目保证最年长和最年轻的人没有并列。
输出格式:
在一行中顺序输出有效生日的个数,最年长人和最年轻人的姓名,其间以空格分隔。
输入样例:
5
John 2001/05/12
Tom 1814/09/06
Ann 2121/01/30
James 1814/09/05
Steve 1967/11/20
输出样例:
3 Tom John
解题思路:
首先,根据题意可知这个人口普查其实就是2个变量而已嘛,一个name,一个birthday,那就直接建立一个person结构体好了。然后根据题目要求这个岛上的人生日在1814/09/06至2014/09/06这个范围内,接下来直接用for循环对输入进行遍历来求解在这个范围内的有效生日并找出最年长和最年轻的人所在的下标就好了。然而!我第一次提交的时候有个测试用例WA了,找了N久之后终于发现当有效个数为0时,后面不能够输出多余的空格。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 struct person 5 { 6 string name,birthday; 7 }; 8 9 int main() 10 { 11 int n; 12 cin >> n; 13 string start = "1814/09/06"; 14 string end = "2014/09/06"; 15 person p[n]; 16 int count=0; 17 bool flag = true; 18 int minIndex,maxIndex; 19 for (int i = 0; i < n; i++) 20 { 21 cin >> p[i].name >> p[i].birthday; 22 if(p[i].birthday>=start && p[i].birthday<=end) 23 { 24 count++; 25 if(flag) 26 { 27 flag = false; 28 minIndex = i, maxIndex = i; 29 } 30 else 31 { 32 if(p[minIndex].birthday>p[i].birthday) 33 { 34 minIndex = i; 35 } 36 if(p[maxIndex].birthday<p[i].birthday) 37 { 38 maxIndex = i; 39 } 40 } 41 } 42 } 43 if(count != 0) 44 { 45 cout << count << " " << p[minIndex].name << " " << p[maxIndex].name << endl; 46 } 47 else //有效个数为0时,输出0且后面不能有空格 48 { 49 cout << count << endl; 50 } 51 return 0; 52 }
11.旧键盘(20 分)
题目描述:
旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现。现在给出应该输入的一段文字,以及实际被输入的文字,请你列出肯定坏掉的那些键。
输入格式:
输入在2行中分别给出应该输入的文字,以及实际被输入的文字。每段文字是不超过80个字符的串,由字母AZ(包括大,小写),数字0-9,以及下划线“ _”(代表空格)组成。题目保证2个字符串均非空。
输出格式:
按照发现顺序,在一行中输出坏掉的键。其中英文字母只输出大写,每个坏键只输出一次。题目保证至少有1个坏键。
输入样例:
7_This_is_a_test
_hs_s_a_es
输出样例:
7TI
解题思路:
首先,根据题意脑子里冒出一句话“Life is short, use python!” 用for循环来遍历应该输入的蚊子,如果一个字符是应该输入的但实际上未被输入,就用upper()把这个字符转换成大写形式存入bad_key这个列表中,接下来就是对bad_key这个列表去重输出。先利用set()来对bad_key()进行去重,然后再用list()将bad_key()转换回列表,在完成这个去重操作的同时,用sorted()函数来保留bad_key原有的顺序,最后用join把bad_key中所有的元素添加到一个空字符串中进行输出。
AC代码:
1 s,a = input(),input()
2 bad_key = [i.upper() for i in s if i not in a]
3 print("".join(sorted(list(set(bad_key)),key=bad_key.index)))
12. 旧键盘打字(20 分)
题目描述:
旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现。现在给出应该输入的一段文字、以及坏掉的那些键,打出的结果文字会是怎样?
输入格式:
输入在2行中分别给出坏掉的那些键、以及应该输入的文字。其中对应英文字母的坏键以大写给出;每段文字是不超过10^5个字符的串。可用的字符包括字母[a-z, A-Z]、数字0-9、以及下划线“_”(代表空格)、“,”、“.”、“-”、“+”(代表上档键)。题目保证第2行输入的文字串非空。 注意:如果上档键坏掉了,那么大写的英文字母无法被打出。
输出格式:
在一行中输出能够被打出的结果文字。如果没有一个字符能被打出,则输出空行。
输入样例:
7+IE.
7_This_is_a_test.
输出样例:
_hs_s_a_tst
解题思路:
首先,看完题目之后发现它和上一题很相似,还是那句话“Life is short, use python!” 虽然思路也很简单,但是! 这次的代码有点长啊,我是先把bad_key里面所有的大写字母都转换成小写字母,转换的同时在打印结果result中删去坏键。如果bad_key里面有'+'号,则说明上档键是坏的,无法输出大写字母,所以当strinput中的字符是大写且上档键是坏的时,就将这个大写的坏键在打印结果result中删去,最后输出能打印出来的字符。
AC代码:
1 badKey,strinput = input(),input() 2 result = strinput 3 for i in badKey: 4 if badKey.isupper(): #如果坏键是大写字母,则替换成小写字母 5 result = result.replace(i.lower(),"") 6 result = result.replace(i, "") #坏键字符全部从打印结果中删去 7 if badKey.find('+') > -1: #如果含有上档键 8 for i in set(list(result)): #把预期打印结果转换成set去重,再进行大写字母的查找 9 if i.isupper(): #若找到大写字母,就把它从打印结果中删去 10 result = result.replace(i, "") 11 print(result)
13 .跟奥巴马一起编程(15 分)
题目描述:
美国总统奥巴马不仅呼吁所有人都学习编程,甚至以身作则编写代码,成为美国历史上首位编写计算机代码的总统2014年底,为庆祝“计算机科学教育周”正式启动,奥巴马编写了很简单的计算机代码:在屏幕上画一个正方形。现在你也跟他一起画吧!
输入格式:
输入在一行中给出正方形边长N(3 <= N <= 20)和组成正方形边的某种字符C,间隔一个空格。
输出格式:
输出由给定字符Ç画出的正方形。但是注意到行间距比列间距大,所以为了让结果看上去更像正方形,我们输出的行数实际上是列数的50%(四舍五入取整)。
输入样例:
10 a
输出样例:
aaaaaaaaaa
a a
a a
a a
aaaaaaaaaa
解题思路:
首先,根据题意可知行数是列数的50%(四舍五入取整),输入的边长也就是col列数,然后利用round()函数来四舍五入求row行数,接着利用for循环嵌套,在第一行、最后一行输出字符c,在中间行的第一列和最后一列输出字符c,其余位置输出空格。
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 int main()
5 {
6 int col;
7 char c;
8 cin >> col >> c;
9 int row = round(col/2.0); //通过round来实现四舍五入
10 for(int i=0;i<row;i++)
11 {
12 for (int j=0;j<col;j++)
13 {
14 if(i==0||j==0||i==row-1||j==col-1) //只在正方形的边长部分输出字符c
15 {
16 cout << c;
17 }
18 else cout << " "; //其余部分全是空格
19 }
20 cout << endl;
21 }
22 return 0;
23 }
14.月饼 (25 分)
题目描述:
月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼。现给定所有种类月饼的库存量、总售价、以及市场的最大需求量,请你计算可以获得的最大收益是多少。
注意:销售时允许取出一部分库存。样例给出的情形是这样的:假如我们有3种月饼,其库存量分别为18、15、10万吨,总售价分别为75、72、45亿元。如果市场的最大需求量只有20万吨,那么我们最大收益策略应该是卖出全部15万吨第2种月饼、以及5万吨第3种月饼,获得72 + 45/2 = 94.5(亿元)。
输入格式:
每个输入包含1个测试用例。每个测试用例先给出一个不超过1000的正整数N表示月饼的种类数、以及不超过500(以万吨为单位)的正整数D表示市场最大需求量。随后一行给出N个正数表示每种月饼的库存量(以万吨为单位);最后一行给出N个正数表示每种月饼的总售价(以亿元为单位)。数字间以空格分隔。
输出格式:
对每组测试用例,在一行中输出最大收益,以亿元为单位并精确到小数点后2位。
输入样例:
3 20
18 15 10
75 72 45
输出样例:
94.50
解题思路:
首先,通过题意可知月饼有3个变量:库存量,总售价,单价。所以,先建一个含有这3个变量的moonCake结构体,然后依次输入月饼的种类数、需求量,每种月饼的库存量和总售价。在算出月饼的单价之后,根据单价从高到低用sort来对月饼进行排序。最后通过需求量和月饼的库存量大小的比较来求利润。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 struct moonCake 5 { 6 double amount; //月饼的库存量 7 double totalPrice; //月饼的总售价 8 double unitPrice; //月饼的单价 9 }; 10 11 bool cmp(moonCake &m1,moonCake &m2) //按月饼的单价对月饼进行排序 12 { 13 return m1.unitPrice > m2.unitPrice; 14 } 15 16 int main() 17 { 18 int N, D; //N为月饼的种类数,D为市场最大需求量 19 cin >> N >> D; 20 moonCake m[N]; 21 for (int i = 0; i < N; i++) 22 { 23 cin >> m[i].amount; 24 } 25 for (int i = 0; i < N; i++) 26 { 27 cin >> m[i].totalPrice; 28 m[i].unitPrice = double(m[i].totalPrice)/m[i].amount; 29 } 30 sort(m,m+N,cmp); 31 double profit = 0; //总利润 32 int i = 0; 33 while(D>0) 34 { 35 if(D >= m[i].amount) 36 { 37 D -= m[i].amount; 38 profit += m[i].totalPrice; 39 } 40 else 41 { 42 profit += m[i].unitPrice*D; 43 break; 44 } 45 i++; 46 } 47 printf("%.2f ", profit); 48 return 0; 49 }
15. 有几个PAT(25 分)
题目描述:
字符串APPAPT中包含了两个单词“PAT”,其中第一个PAT是第2位(P),第4位(A),第6位(T);第二个PAT是第3位(P),第4位(A),第6位(T)。现给定字符串,问一共可以形成多少个PAT?
输入格式:
输入只有一行,包含一个字符串,长度不超过105,只包含P,A,T三种字母。
输出格式:
在一行中输出给定字符串中包含多少个PAT。由于结果可能比较大,只输出对1000000007取余数的结果。
输入样例:
APPAPT
输出样例:
2
解题思路:
首先,这个题看完之后有点懵逼,然后仔细分析得出这三点:①每个甲对应的PA组合数量是甲之前P的数量;②每个Ť对应的PAT组合数量是Ť之前所有甲对应的PA组合数量的累加;③所有的PAT组合数量是所有Ť对应的PAT组合数量的累加。
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 int main()
5 {
6 string s;
7 cin >> s;
8 int len = s.length();
9 int result = 0, countp = 0, countpa = 0, countpat = 0;
10 for (auto i:s)
11 {
12 if(i == 'P')
13 {
14 countp++;
15 }
16 else if(i == 'A')
17 {
18 countpa += countp;
19 }
20 else if(i == 'T')
21 {
22 countpat += countpa;
23 countpat %= 1000000007;
24 }
25 }
26 cout << countpat<< endl;
27 return 0;
28 }
16. 统计同成绩学生 (20 分)
题目描述:
本题要求读入 N 名学生的成绩,将获得某一给定分数的学生人数输出。
输入格式:
输入在第 1 行给出不超过 105 的正整数 N,即学生总人数。随后一行给出 N 名学生的百分制整数成绩,中间以空格分隔。最后一行给出要查询的分数个数 K(不超过 N 的正整数),随后是 K 个分数,中间以空格分隔。
输出格式:
在一行中按查询顺序给出得分等于指定分数的学生人数,中间以空格分隔,但行末不得有多余空格。
输入样例:
10
60 75 90 55 75 99 82 90 75 50
3 75 90 88
输出样例:
3 2 0
解题思路:
首先看完题目之后,第一反应就是这是水题,只需要建立一个map来存放学生的分数并且统计每个分数有多少人就行了,map建立出来了之后按题目要求输出,就可以看下一道题了。
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 int main()
5 {
6 ios::sync_with_stdio(false);
7 //取消cin和stdin的同步,第一次提交的时候有个测试用例TLE了
8 map<int,int> m;
9 int n,temp;
10 cin >> n;
11 for (int i = 0; i < n; i++)
12 {
13 cin >> temp;
14 m[temp]++;
15 }
16 int k;
17 cin >> k;
18 for (int i = 0; i < k; i++)
19 {
20 cin >> temp;
21 cout << m[temp];
22 if(i < k-1)
23 {
24 cout << " ";
25 }
26 }
27 return 0;
28 }
17. 成绩排名 (20 分)
题目描述:
读入 n(>0)名学生的姓名、学号、成绩,分别输出成绩最高和成绩最低学生的姓名和学号。
输入格式:
每个测试输入包含 1 个测试用例,格式为
第 1 行:正整数 n
第 2 行:第 1 个学生的姓名 学号 成绩
第 3 行:第 2 个学生的姓名 学号 成绩
... ... ...
第 n+1 行:第 n 个学生的姓名 学号 成绩
其中姓名
和学号
均为不超过 10 个字符的字符串,成绩为 0 到 100 之间的一个整数,这里保证在一组测试用例中没有两个学生的成绩是相同的。
输出格式:
对每个测试用例输出 2 行,第 1 行是成绩最高学生的姓名和学号,第 2 行是成绩最低学生的姓名和学号,字符串间有 1 空格。
输入样例:
3
Joe Math990112 89
Mike CS991301 100
Mary EE990830 95
输出样例:
Mike CS991301
Joe Math990112
解题思路:
首先看完题目之后,建立一个vector来对学生的信息进行存储,利用sort函数根据学生分数降序来对学生进行排序,输出成绩最高和最低的学生信息即可。
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 struct stu
5 {
6 string name;
7 string ID;
8 int score;
9 };
10
11 bool Cmp(struct stu & a, struct stu & b)
12 {
13 return a.score > b.score;
14 }
15
16 int main()
17 {
18 int n;
19 while (cin >> n)
20 {
21 vector<struct stu> v(n);
22 for (int i = 0; i < n; i++)
23 {
24 cin >> v[i].name >> v[i].ID >> v[i].score;
25 }
26 sort(v.begin(), v.end(), Cmp);
27 cout << v[0].name << " " << v[0].ID << endl;
28 cout << v[v.size()-1].name << " " << v[v.size() - 1].ID << endl;
29 }
30 return 0;
31 }
18. 考试座位号 (15 分)
题目描述:
每个 PAT 考生在参加考试时都会被分配两个座位号,一个是试机座位,一个是考试座位。正常情况下,考生在入场时先得到试机座位号码,入座进入试机状态后,系统会显示该考生的考试座位号码,考试时考生需要换到考试座位就座。但有些考生迟到了,试机已经结束,他们只能拿着领到的试机座位号码求助于你,从后台查出他们的考试座位号码。
输入格式:
输入第一行给出一个正整数 N(≤1000),随后 N 行,每行给出一个考生的信息:准考证号 试机座位号 考试座位号
。其中准考证号
由 14 位数字组成,座位从 1 到 N 编号。输入保证每个人的准考证号都不同,并且任何时候都不会把两个人分配到同一个座位上。
考生信息之后,给出一个正整数 M(≤N),随后一行中给出 M 个待查询的试机座位号码,以空格分隔。
输出格式:
对应每个需要查询的试机座位号码,在一行中输出对应考生的准考证号和考试座位号码,中间用 1 个空格分隔。
输入样例:
4
10120150912233 2 4
10120150912119 4 1
10120150912126 1 3
10120150912002 3 2
2
3 4
输出样例:
10120150912002 2
10120150912119 1
解题思路:
首先看完题目之后,建立一个vector来对学生的信息进行存储,利用sort函数根据学生试机座位号升序来对学生进行排序,对vector进行遍历找到要查找的试机座位号,输出学生的准考证号和考试座位号即可。
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 struct stu
5 {
6 string ID;
7 int seat1,seat2; //分别为试机座位号和考试座位号
8 };
9
10 bool Cmp(stu s1,stu &s2)
11 {
12 return s1.seat1 < s2.seat2;
13 }
14
15 int main()
16 {
17 int n;
18 cin >> n;
19 vector<struct stu> v(n);
20 for (int i = 0; i < n; i++)
21 {
22 cin >> v[i].ID >> v[i].seat1 >> v[i].seat2;
23 }
24 sort(v.begin(),v.end(),Cmp);
25 int m;
26 cin >> m;
27 for (int i = 0; i < m; i++)
28 {
29 int temp;
30 cin >> temp;
31 for (int j = 0; j < n; j++)
32 {
33 if(v[j].seat1 == temp)
34 {
35 cout << v[j].ID << " " << v[j].seat2 << endl;
36 }
37 }
38 }
39 return 0;
40 }
19. 射击比赛 (20 分)
题目描述:
本题目给出的射击比赛的规则非常简单,谁打的弹洞距离靶心最近,谁就是冠军;谁差得最远,谁就是菜鸟。本题给出一系列弹洞的平面坐标(x,y),请你编写程序找出冠军和菜鸟。我们假设靶心在原点(0,0)。
输入格式:
输入在第一行中给出一个正整数 N(≤ 10 000)。随后 N 行,每行按下列格式给出:
ID x y
其中 ID
是运动员的编号(由 4 位数字组成);x
和 y
是其打出的弹洞的平面坐标(x
,y
),均为整数,且 0 ≤ |x
|, |y
| ≤ 100。题目保证每个运动员的编号不重复,且每人只打 1 枪。
输出格式:
输出冠军和菜鸟的编号,中间空 1 格。题目保证他们是唯一的。
输入样例:
3
0001 5 7
1020 -1 3
0233 0 -1
输出样例:
0233 0001
解题思路:
首先,看完题目就可以知道,这跟前面的俩道题几乎是用了同一个答题模板。建立一个vector来对运动员的信息进行存储,利用sort函数根据弹孔离靶心距离来对运动员进行排序,最后输出冠军和菜鸟即可。
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 struct Athlete
5 {
6 string ID;
7 int x,y;
8 double distance;
9 };
10
11 bool Cmp(Athlete a1,Athlete a2)
12 {
13 return a1.distance > a2.distance;
14 }
15
16 int main()
17 {
18 int n;
19 cin >> n;
20 vector<struct Athlete> v(n);
21 for (int i = 0; i < n; i++)
22 {
23 cin >> v[i].ID >> v[i].x >> v[i].y;
24 v[i].distance = sqrt(v[i].x*v[i].x + v[i].y*v[i].y);
25 }
26 sort(v.begin(),v.end(),Cmp);
27 cout << v[v.size()-1].ID << " " << v[0].ID << endl;
28 return 0;
29 }
20. 换个格式输出整数 (15 分)
题目描述:
让我们用字母 B
来表示“百”、字母 S
表示“十”,用 12...n
来表示不为零的个位数字 n
(<10),换个格式来输出任一个不超过 3 位的正整数。例如 234
应该被输出为 BBSSS1234
,因为它有 2 个“百”、3 个“十”、以及个位的 4。
输入格式:
每个测试输入包含 1 个测试用例,给出正整数 n(<1000)。
输出格式:
每个测试用例的输出占一行,用规定的格式输出 n。
输入样例 1:
234
输出样例 1:
BBSSS1234
输入样例 2:
23
输出样例 2:
SS123
解题思路:
首先,通过这个题目的输入输出样例可知,输入的数字n的百位数是多少就输出多少个'B',十位数是多少就输出多少个'S',个位数是多少就从1开始一直输出到这个数为止。
AC代码:
1 #include <bits/stdc++.h>(
2 using namespace std;
3
4 int main()
5 {
6 int n;
7 cin >> n;
8 int b = n/100;
9 int s = n%100/10;
10 int g = n%10;
11 for(int i=0;i<b;i++)
12 {
13 cout << "B";
14 }
15 for(int i=0;i<s;i++)
16 {
17 cout << "S";
18 }
19 for(int i=1;i<=g;i++)
20 {
21 cout << i;
22 }
23 cout << endl;
24 return 0;
25 }
21. 字符统计 (20 分)
题目描述:
请编写程序,找出一段给定文字中出现最频繁的那个英文字母。
输入格式:
输入在一行中给出一个长度不超过 1000 的字符串。字符串由 ASCII 码表中任意可见字符及空格组成,至少包含 1 个英文字母,以回车结束(回车不算在内)。
输出格式:
在一行中输出出现频率最高的那个英文字母及其出现次数,其间以空格分隔。如果有并列,则输出按字母序最小的那个字母。统计时不区分大小写,输出小写字母。
输入样例:
This is a simple TEST. There ARE numbers and other symbols 1&2&3...........
输出样例:
e 7
解题思路:
首先看完题目之后,脑子里冒出一句话“人生苦短....”这题涉及到了字符串的大小写转换、字母出现次数的统计和字符大小比较,果断用Python写。第一行操作很骚,input().split()是把用户输入以空格为分隔符存入一个列表里面,然后利用" ".join()把刚刚生成的列表中的所有元素存入字符串中,最后再用一个lower()来把字符串的所有大写字母转换成小写。输入解决了,接下来的事也很简单,遍历字符串s中的所有元素,如果这个字符是字母就判断它的出现次数是否最频繁,如果有出现次数一样频繁的多个字符,则输出字母序最小的那一个。
AC代码:
1 s = (" ".join(input().split())).lower()
2 max_count = 0
3 for i in s:
4 if i.isalpha():
5 if s.count(i) > max_count:
6 max_count = s.count(i)
7 max_char = i
8 elif s.count(i) == max_count:
9 if i < max_char:
10 max_char = i
11 print("{} {}".format(max_char,max_count))
22. 判断题 (15 分)
题目描述:
判断题的评判很简单,本题就要求你写个简单的程序帮助老师判题并统计学生们判断题的得分。
输入格式:
输入在第一行给出两个不超过 100 的正整数 N 和 M,分别是学生人数和判断题数量。第二行给出 M 个不超过 5 的正整数,是每道题的满分值。第三行给出每道题对应的正确答案,0 代表“非”,1 代表“是”。随后 N 行,每行给出一个学生的解答。数字间均以空格分隔。
输出格式:
按照输入的顺序输出每个学生的得分,每个分数占一行。
输入样例:
3 6
2 1 3 3 4 5
0 0 1 0 1 1
0 1 1 0 0 1
1 0 1 0 1 0
1 1 0 0 1 1
输出样例:
13
11
12
解题思路:
首先看完题目之后,按它的意思来就行了,建立一个数组来存放每道题的分值、建立一个数组来存取正确答案,然后输入每个学生的答案与正确答案一一比较计算出学生的分数进行输出即可。
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 int main()
5 {
6 int n, m;
7 cin >> n >> m; //n为学生数,m为判断题数量
8 int weight[m]; //每道题目的满分值
9 for (int i = 0; i < m; i++)
10 {
11 cin >> weight[i];
12 }
13 int trueAnswer[m]; //每道题对应的正确答案
14 for (int i = 0; i < m; i++)
15 {
16 cin >> trueAnswer[i];
17 }
18 int stuAnswer[m];
19 for (int i = 0; i < n; i++)
20 {
21 int score = 0;
22 for (int j = 0; j < m; j++)
23 {
24 cin >> stuAnswer[j];
25 if(stuAnswer[j] == trueAnswer[j])
26 {
27 score += weight[j];
28 }
29 }
30 cout << score << endl;
31 }
32 return 0;
33 }
23. Wifi密码 (15 分)
题目描述:
下面是微博上流传的一张照片:“各位亲爱的同学们,鉴于大家有时需要使用 wifi,又怕耽误亲们的学习,现将 wifi 密码设置为下列数学题答案:A-1;B-2;C-3;D-4;请同学们自己作答,每两日一换。谢谢合作!!~”—— 老师们为了促进学生学习也是拼了…… 本题就要求你写程序把一系列题目的答案按照卷子上给出的对应关系翻译成 wifi 的密码。这里简单假设每道选择题都有 4 个选项,有且只有 1 个正确答案。
输入格式:
输入第一行给出一个正整数 N(≤ 100),随后 N 行,每行按照 编号-答案
的格式给出一道题的 4 个选项,T
表示正确选项,F
表示错误选项。选项间用空格分隔。
输出格式:
在一行中输出 wifi 密码。
输入样例:
8
A-T B-F C-F D-F
C-T B-F A-F D-F
A-F D-F C-F B-T
B-T A-F C-F D-F
B-F D-T A-F C-F
A-T C-F B-F D-F
D-T B-F C-F A-F
C-T A-F B-F D-F
输出样例:
13224143
解题思路:
首先看完题目之后,果断用Python,重点是第三行代码,利用字符串中的find函数在输入的字符串s中寻找'T',将find函数的返回int型的值减去2就可以得到这一题正确答案,然而我们还需要调用ord()来把字符转换成ASCⅡ码,减去'A'再加1就可以得到题目所要求的A-1;B-2;C-3;D-4;输出就是WIFI密码。 (我自己顺便记一下笔记:ASCⅡ码转成字符是用chr(),字符转ASCⅡ码是用ord(),一开始我直接用int,编译器报错了,然后我百度了一下Python字符和ASCⅡ码间的转换)
AC代码:
for i in range(eval(input())):
s = input()
print(ord(s[s.find('T')-2])-ord('A')+1,end="")
24. 小赌怡情 (15 分)
题目描述:
常言道“小赌怡情”。这是一个很简单的小游戏:首先由计算机给出第一个整数;然后玩家下注赌第二个整数将会比第一个数大还是小;玩家下注 t 个筹码后,计算机给出第二个数。若玩家猜对了,则系统奖励玩家 t 个筹码;否则扣除玩家 t 个筹码。
注意:玩家下注的筹码数不能超过自己帐户上拥有的筹码数。当玩家输光了全部筹码后,游戏就结束。
输入格式:
输入在第一行给出 2 个正整数 T 和 K(≤ 100),分别是系统在初始状态下赠送给玩家的筹码数、以及需要处理的游戏次数。随后 K 行,每行对应一次游戏,顺序给出 4 个数字:
n1 b t n2
其中 n1
和 n2
是计算机先后给出的两个[0, 9]内的整数,保证两个数字不相等。b
为 0 表示玩家赌小
,为 1 表示玩家赌大
。t
表示玩家下注的筹码数,保证在整型范围内。
输出格式:
对每一次游戏,根据下列情况对应输出(其中 t
是玩家下注量,x
是玩家当前持有的筹码量):
- 玩家赢,输出
Win t! Total = x.
; - 玩家输,输出
Lose t. Total = x.
; - 玩家下注超过持有的筹码量,输出
Not enough tokens. Total = x.
; - 玩家输光后,输出
Game Over.
并结束程序。
输入样例 1:
100 4
8 0 100 2
3 1 50 1
5 1 200 6
7 0 200 8
输出样例 1:
Win 100! Total = 200.
Lose 50. Total = 150.
Not enough tokens. Total = 150.
Not enough tokens. Total = 150.
输入样例 2:
100 4
8 0 100 2
3 1 200 1
5 1 200 6
7 0 200 8
输出样例 2:
Win 100! Total = 200.
Lose 200. Total = 0.
Game Over.
解题思路:
首先看完题目之后,想起来了我赌球时的伤心往事,插个题外话,真的这辈子别碰赌这个字。下面请听输了4.3个的18岁老哥对赌的看法,NBA的大小分也好,足球的大小球也好,先不考虑庄狗操盘控盘的情况,表面上看上去我们的赢面和庄狗是五五开,而根据概率论,两个赢面五五开的对手,资本小的一方必定先破产。打个很浅显的比方:石头剪刀布赢面是不是五五开?我资本只有100,你资本有1000,10块钱一把,不出2分钟我就有可能破产,因为根据赌徒心理,赢了就想着追加投注以更少的游戏次数来赢更多的钱,输了就会上头想着靠倍投来扳回上一把的本。反正,我这辈子坚决不会再碰了,好好学习努力奋斗才能梦想成真。不幸中的万幸就是我在18岁的时候就犯下了这个错误看透了赌的本质,以后真正有了大钱也就不会去赌了,在这期间也明白了不少人生道理,这里就不再扯了。哎 成长是个很痛的名词,是要付出代价的,这些输掉的钱就当是给人生交了一笔不小的学费了,我爸妈已经原谅我了,是个人就会有犯错的时候,以后不栽在同样的错误上就行,赌球可以输,但是人生不能!好了,走远了回到这道题,算了,这道题真的不难,直接上代码看注释吧。
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 int main()
5 {
6 int T,K; //T为玩家初始筹码数,K为游戏次数
7 cin >> T >> K;
8 int x = T; //x是玩家持有的筹码量
9 for (int i = 0; i < K; i++)
10 {
11 int n,b,t,m; //n和m为整数,n为盘口,m为结果,b表示玩家买大买小,t是下注的筹码数
12 cin >> n >> b >> t >> m;
13 if(t > x)
14 {
15 printf("Not enough tokens. Total = %d.
",x);
16 continue; //直接进入下一局游戏
17 }
18 if(b == 1) //玩家买大
19 {
20 if(n < m) //猜中了
21 {
22 x += t;
23 printf("Win %d! Total = %d.
",t,x);
24 }
25 else //没猜中
26 {
27 x -= t;
28 printf("Lose %d. Total = %d.
",t,x);
29 }
30 }
31 else //玩家买小
32 {
33 if(n > m) //猜中了
34 {
35 x += t;
36 printf("Win %d! Total = %d.
",t,x);
37 }
38 else //没猜中
39 {
40 x -= t;
41 printf("Lose %d. Total = %d.
",t,x);
42 }
43 }
44 if(x <= 0) //玩家输光之后
45 {
46 cout << "Game Over." << endl;
47 break;
48 }
49 }
50 return 0;
51 }
25. 有多少不同的值 (20 分)
题目描述:
当自然数 n 依次取 1、2、3、……、N 时,算式 ⌊n/2⌋+⌊n/3⌋+⌊n/5⌋ 有多少个不同的值?(注:⌊x⌋ 为取整函数,表示不超过 x 的最大自然数,即 x 的整数部分。)
输入格式:
输入给出一个正整数 N(2≤N≤104)。
输出格式:
在一行中输出题面中算式取到的不同值的个数。
输入样例:
2017
输出样例:
1480
解题思路:
首先看完题目之后,第一想法就是建立一个map来记录不同值,看清题 for循环是从1开始遍历的,向下取整用的是floor函数,最后输出map的大小也就是不同值的个数。
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 int main()
5 {
6 int n;
7 cin >> n;
8 map<int,int> m;
9 for (int i = 1; i <= n; i++)
10 {
11 int temp = floor(i/2) + floor(i/3) + floor(i/5);
12 m[temp]++;
13 }
14 cout << m.size() << endl;
15 return 0;
16 }
26. 写出这个数 (20 分)
题目描述:
读入一个正整数 n,计算其各位数字之和,用汉语拼音写出和的每一位数字。
输入格式:
每个测试输入包含 1 个测试用例,即给出自然数 n 的值。这里保证 n 小于 10100。
输出格式:
在一行内输出 n 的各位数字之和的每一位,拼音数字间有 1 空格,但一行中最后一个拼音数字后没有空格。
输入样例:
1234567890987654321123456789
输出样例:
yi san wu
解题思路:
首先看完题目之后,我先自定义了一个transfer()函数用来将数字转换为拼音。然后根据题目意思来吧。我是用string来存放输入的数字的,然后用for循环将每一个数字取出来累加,算出累加和的个位十位百位分别是多少,然后调用自定义函数来完成转换。值得一提的是,我第一遍写的那段代码有一个测试用例无法通过,因为当sum的十位数是0是会无法输出'ling',比如999999999999这个输入,预期输出应该是"yi ling ba",然而实际输出是"yi ba",知道错误原因之后,把那两个if if改成if和else if和else就能通过所有测试用例了。
AC代码:
1 #include <bits/stdc++.h>
2 using namespace std;
3
4 void transfer(int n)
5 {
6 switch(n)
7 {
8 case 0: cout << "ling"; break;
9 case 1: cout << "yi"; break;
10 case 2: cout << "er"; break;
11 case 3: cout << "san"; break;
12 case 4: cout << "si"; break;
13 case 5: cout << "wu"; break;
14 case 6: cout << "liu"; break;
15 case 7: cout << "qi"; break;
16 case 8: cout << "ba"; break;
17 case 9: cout << "jiu"; break;
18 default : break;
19 }
20 }
21
22 int main()
23 {
24 string number;
25 cin >> number;
26 int len = number.length();
27 int sum = 0;
28 for(int i=0;i<len;i++)
29 {
30 sum += number[i]-'0';
31 }
32 int b = sum/100;
33 int s = sum%100/10;
34 int g = sum%10;
35 if(b != 0)
36 {
37 transfer(b);
38 cout << " ";
39 transfer(s);
40 cout << " ";
41 transfer(g);
42 }
43 else if(s != 0)
44 {
45 transfer(s);
46 cout << " ";
47 transfer(g);
48 }
49 else
50 {
51 transfer(g);
52 }
53 /*我之前是这样写的,结果有个测试用例没给我通过
54 if(b != 0)
55 {
56 transfer(b);
57 cout << " ";
58 }
59 if(s != 0)
60 {
61 transfer(s);
62 cout << " ";
63 }
64 transfer(g);
65 */
66 return 0;
67 }
27. 划拳 (15 分)
题目描述:
划拳是古老中国酒文化的一个有趣的组成部分。酒桌上两人划拳的方法为:每人口中喊出一个数字,同时用手比划出一个数字。如果谁比划出的数字正好等于两人喊出的数字之和,谁就赢了,输家罚一杯酒。两人同赢或两人同输则继续下一轮,直到唯一的赢家出现。
下面给出甲、乙两人的划拳记录,请你统计他们最后分别喝了多少杯酒。
输入格式:
输入第一行先给出一个正整数 N(≤100),随后 N 行,每行给出一轮划拳的记录,格式为:
甲喊 甲划 乙喊 乙划
其中喊
是喊出的数字,划
是划出的数字,均为不超过 100 的正整数(两只手一起划)。
输出格式:
在一行中先后输出甲、乙两人喝酒的杯数,其间以一个空格分隔。
输入样例:
5 8 10 9 12 5 10 5 10 3 8 5 12 12 18 1 13 4 16 12 15
输出样例:
1 2
解题思路:
首先看完题目之后,发现这是水题,直接按照题目的意思来,思路见注释。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int n; 7 cin >> n; 8 int m1, h1, count1 = 0; //m1是甲口中喊出的数,h1是甲用手比划的数,count1是甲喝酒的杯数 9 int m2, h2, count2 = 0; //m2是乙口中喊出的数,h2是乙用手比划的数,count2是乙喝酒的杯数 10 for (int i = 0; i < n; i++) 11 { 12 cin >> m1 >> h1 >> m2 >> h2; 13 if(m1+m2==h1 && m1+m2!=h2) //若只有甲比划的数字正好是俩人喊出的数字之和 14 { 15 count2++; //乙自罚一杯 16 } 17 else if(m1+m2!=h1 && m1+m2==h2) //若只有乙比划的数字正好是俩人喊出的数字之和 18 { 19 count1++; //甲自罚一杯 20 } 21 else //剩下的情况就是甲乙平局 22 { 23 continue; //继续下一轮 24 } 25 } 26 cout << count1 << " " << count2 << endl; 27 return 0; 28 }
28. 数字黑洞 (20 分)
题目描述:
给定任一个各位数字不完全相同的 4 位正整数,如果我们先把 4 个数字按非递增排序,再按非递减排序,然后用第 1 个数字减第 2 个数字,将得到一个新的数字。一直重复这样做,我们很快会停在有“数字黑洞”之称的 6174
,这个神奇的数字也叫 Kaprekar 常数。
例如,我们从6767
开始,将得到
7766 - 6677 = 1089 9810 - 0189 = 9621 9621 - 1269 = 8352 8532 - 2358 = 6174 7641 - 1467 = 6174 ... ...
现给定任意 4 位正整数,请编写程序演示到达黑洞的过程。
输入格式:
输入给出一个 (0,104) 区间内的正整数 N。
输出格式:
如果 N 的 4 位数字全相等,则在一行内输出 N - N = 0000
;否则将计算的每一步在一行内输出,直到 6174
作为差出现,输出格式见样例。注意每个数字按 4
位数格式输出。
输入样例 1:
6767
输出样例 1:
7766 - 6677 = 1089 9810 - 0189 = 9621 9621 - 1269 = 8352 8532 - 2358 = 6174
输入样例 2:
2222
输出样例 2:
2222 - 2222 = 0000
解题思路:
首先看完题目之后,有一点懵,又看了俩边终于明白题目的意思了。第一步:将输入的数字按照个十百千位来进行非递增排序和非递减排序,第二步:用新生成的那个非递增排序的数减去非递减排序的数,第三步:将第二部得到的差重新进行第一步的操作,直到得到6174为止。若第一步中输入的那个数字个十百千位都相等,差值就输出0000。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int arr2num(int a[]) //把数组里的数按照下标次序来组成一个新的数字 5 { 6 int n = 0; 7 for (int i = 0; i < 4; i++) 8 { 9 n = n*10 + a[i]; 10 } 11 return n; 12 } 13 14 bool Cmp(int a, int b) 15 { 16 return a>b; 17 } 18 int main() 19 { 20 int n; 21 cin >> n; 22 int a[4]; 23 do 24 { 25 for (int i=0;i<4;i++) //把每一位数存入数组里面 26 { 27 a[i] = n%10; 28 n /=10; 29 } 30 sort(a,a+4); //将数组a中的元素升序排列 31 int x = arr2num(a); //将数组a中的数字按非递减排序 32 sort(a,a+4,Cmp); //将数组a中的元素降序排列 33 int y = arr2num(a); //将数组a中的数字按非递增排序 34 n = y-x; 35 printf("%04d - %04d = %04d ",y,x,n); 36 }while(n!=0 && n!=6174); 37 return 0; 38 }
29. 输出PATest (20 分)
题目描述:
给定一个长度不超过 104 的、仅由英文字母构成的字符串。请将字符重新调整顺序,按 PATestPATest....
这样的顺序输出,并忽略其它字符。当然,六种字符的个数不一定是一样多的,若某种字符已经输出完,则余下的字符仍按 PATest 的顺序打印,直到所有字符都被输出。
输入格式:
输入在一行中给出一个长度不超过 104 的、仅由英文字母构成的非空字符串。
输出格式:
在一行中按题目要求输出排序后的字符串。题目保证输出非空。
输入样例:
redlesPayBestPATTopTeePHPereatitAPPT
输出样例:
PATestPATestPTetPTePePee
解题思路:
首先看完题目之后,第一反应就是建立一个map来记录每种字符有多少个,然后用while和if来操作,让程序按 PATestPATest....
这样的顺序输出。若某种字符已经输出完,则余下的字符仍按 PATest 的顺序打印,直到所有字符都被输出。其实就是按照题目意思来写就行,水题。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 map<char,int> m; 7 string s; 8 cin >> s; 9 for (int i = 0; i < s.length(); i++) 10 { 11 m[s[i]]++; //记录每种字符有多少个 12 } 13 while(m['P']||m['A']||m['T']||m['e']||m['s']||m['t']) 14 //若某种字符已经输出完,则余下的字符仍按 PATest 的顺序打印,直到所有字符都被输出 15 { 16 if(m['P']) 17 { 18 cout << 'P'; 19 m['P']--; 20 } 21 if(m['A']) 22 { 23 cout << 'A'; 24 m['A']--; 25 } 26 if(m['T']) 27 { 28 cout << 'T'; 29 m['T']--; 30 } 31 if(m['e']) 32 { 33 cout << 'e'; 34 m['e']--; 35 } 36 if(m['s']) 37 { 38 cout << 's'; 39 m['s']--; 40 } 41 if(m['t']) 42 { 43 cout << 't'; 44 m['t']--; 45 } 46 } 47 return 0; 48 }
30. A除以B (20 分)
题目描述:
本题要求计算 A/B,其中 A 是不超过 1000 位的正整数,B 是 1 位正整数。你需要输出商数 Q 和余数 R,使得 A=B×Q+R 成立。
输入格式:
输入在一行中依次给出 A 和 B,中间以 1 空格分隔。
输出格式:
在一行中依次输出 Q 和 R,中间以 1 空格分隔。
输入样例:
123456789050987654321 7
输出样例:
17636684150141093474 3
解题思路:
首先看完题目之后,这么大个数直接无脑用Python,关于第一行输入的注释在前面的题中提到了这段代码中最秀的地方就是这个a,b,c=map(int,input().split())啦!map()函数的用法如下:map(func,[seq1,seq2,...])第一个参数接受一个函数名,后面的参数接受一个或多个可Python的函数编程中的map()函数是将FUNC作用于SEQ中的每一个元素,并将所有的调用的结果作为一个列表返回。然后整除和求余即可。
AC代码:
1 a,b=map(int,input().split()) 2 print(str(a//b)+" "+str(a%b))
31. 挖掘机技术哪家强 (20 分)
题目描述:
为了用事实说明挖掘机技术到底哪家强,PAT 组织了一场挖掘机技能大赛。现请你根据比赛结果统计出技术最强的那个学校。
输入格式:
输入在第 1 行给出不超过 105 的正整数 N,即参赛人数。随后 N 行,每行给出一位参赛者的信息和成绩,包括其所代表的学校的编号(从 1 开始连续编号)、及其比赛成绩(百分制),中间以空格分隔。
输出格式:
在一行中给出总得分最高的学校的编号、及其总分,中间以空格分隔。题目保证答案唯一,没有并列。
输入样例:
6 3 65 2 80 1 100 2 70 3 40 3 0
输出样例:
2 150
解题思路:
首先看完之后的第一想法就是建立一个map,其中map的key值是参赛者所属学校的编号,value值是学校的总分。这里用一个max来记录总分最高的那个学校的编号。嗯,最后直接输出就行了。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 map<int, int> m; 7 int n; 8 cin >> n; 9 int max = 0; 10 for (int i = 0; i < n; i++) 11 { 12 int num,score; 13 cin >> num >> score; 14 m[num] += score; 15 if(m[num] > m[max]) 16 { 17 max = num; 18 } 19 } 20 cout << max << " " << m[max] << endl; 21 return 0; 22 }
32. 到底买不买 (20 分)
题目描述:
小红想买些珠子做一串自己喜欢的珠串。卖珠子的摊主有很多串五颜六色的珠串,但是不肯把任何一串拆散了卖。于是小红要你帮忙判断一下,某串珠子里是否包含了全部自己想要的珠子?如果是,那么告诉她有多少多余的珠子;如果不是,那么告诉她缺了多少珠子。
为方便起见,我们用[0-9]、[a-z]、[A-Z]范围内的字符来表示颜色。例如在图1中,第3串是小红想做的珠串;那么第1串可以买,因为包含了全部她想要的珠子,还多了8颗不需要的珠子;第2串不能买,因为没有黑色珠子,并且少了一颗红色的珠子。
输入格式:
每个输入包含 1 个测试用例。每个测试用例分别在 2 行中先后给出摊主的珠串和小红想做的珠串,两串都不超过 1000 个珠子。
输出格式:
如果可以买,则在一行中输出 Yes
以及有多少多余的珠子;如果不可以买,则在一行中输出 No
以及缺了多少珠子。其间以 1 个空格分隔。
输入样例 1:
ppRYYGrrYBR2258 YrR8RrY
输出样例 1:
Yes 8
输入样例 2:
ppRYYGrrYB225 YrR8RrY
输出样例 2:
No 2
解题思路:
首先看完题目之后有点懵啊,莫名其妙就开始慌了。又看了一遍题目之后,决定先建一个map压压惊,用来记录摊主的珠串中不同的珠子的数量。然后按照题意完成输入,在输入摊主珠串的时候记得用map记录每颗珠子的数,在输入小红想要的珠串时,用for循环对珠子进行遍历,如果其中有珠子是map中存在的就可以把它从map中取出来,并让计数器count记录总共取出来多少个。最后看看count和小红想要的珠串长度是否相等,若想等就说明小红可以买下它,输出多出的珠子数;否则说明珠子少了,小红不买它,输出缺少的珠子数。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 map<char, int> m; //用来记录每颗珠子的数 7 string strA,strB; //strA是摊主的珠串,strB是小红想要的珠串 8 cin >> strA >> strB; 9 int lenA = strA.length(); 10 int lenB = strB.length(); 11 for (int i = 0; i < lenA; i++) 12 { 13 m[strA[i]]++; 14 } 15 int count = 0; //用来记录摊主的珠串中有多少小红想要的珠串 16 for (int i = 0; i < lenB; i++) 17 { 18 if(m[strB[i]]>0) 19 { 20 m[strB[i]]--; 21 count++; 22 } 23 } 24 if(lenB==count) 25 { 26 cout << "Yes " << lenA-count << endl; //输出Yes和多余的珠子数 27 } 28 else 29 { 30 cout << "No " << lenB-count << endl; //输出No和少的珠子数 31 } 32 }
33. 火星数字 (20 分)
题目描述:
火星人是以 13 进制计数的:
- 地球人的 0 被火星人称为 tret。
- 地球人数字 1 到 12 的火星文分别为:jan, feb, mar, apr, may, jun, jly, aug, sep, oct, nov, dec。
- 火星人将进位以后的 12 个高位数字分别称为:tam, hel, maa, huh, tou, kes, hei, elo, syy, lok, mer, jou。
例如地球人的数字 29
翻译成火星文就是 hel mar
;而火星文 elo nov
对应地球数字 115
。为了方便交流,请你编写程序实现地球和火星数字之间的互译。
输入格式:
输入第一行给出一个正整数 N(<100),随后 N 行,每行给出一个 [0, 169) 区间内的数字 —— 或者是地球文,或者是火星文。
输出格式:
对应输入的每一行,在一行中输出翻译后的另一种语言的数字。
输入样例:
4 29 5 elo nov tam
输出样例:
hel mar may 115 13
解题思路:
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 void earth2spark(string s); //地球数字转火星文 5 void spark2earth(string s); //火星文转地球数字 6 string a[13] = {"tret", "jan", "feb", "mar", "apr", "may", "jun", "jly", "aug", "sep", "oct","nov", "dec"}; 7 string b[13] = {"", "tam", "hel", "maa", "huh", "tou", "kes", "hei", "elo", "syy","lok", "mer", "jou"}; 8 9 int main() 10 { 11 int n; 12 cin >> n; 13 getchar(); 14 for (int i = 0; i < n; i++) 15 { 16 string temp; 17 getline(cin,temp); 18 if(isdigit(temp[0])) //若输入的temp是数字 19 { 20 earth2spark(temp); 21 } 22 else 23 { 24 spark2earth(temp); 25 } 26 } 27 return 0; 28 } 29 30 void earth2spark(string s) //地球数字转火星文 31 { 32 int n = atoi(s.c_str()); //string型数字转int型数字 33 if(n < 13) //若数字小于13 34 { 35 cout << a[n]; 36 } 37 else //若数字大于13 38 { 39 cout << b[n/13]; //输出转换后的十位数 40 if(n%13!=0) //若有个位数 41 { 42 cout << " " << a[n%13]; 43 } 44 } 45 cout << endl; 46 } 47 48 void spark2earth(string s) //火星文转地球数字 49 { 50 int sum = 0; 51 if(s.length() > 3) 52 { 53 for (int i = 0; i < 13; i++) 54 { 55 if(s.substr(0,3) == b[i]) //第一个火星文单词,地球数字的十位 56 { 57 sum += (i*13); 58 } 59 if(s.substr(4,7) == a[i]) //第二个火星文单词,地球数字的个位 60 { 61 sum += i; 62 } 63 } 64 } 65 else 66 { 67 for (int i = 0; i < 13; i++) 68 { 69 if(s == a[i]) //若火星文单词是个位 70 { 71 sum += i; 72 break; 73 } 74 if(s == b[i]) //若火星文单词是十位 75 { 76 sum += (i*13); 77 break; 78 } 79 } 80 } 81 cout << sum << endl; 82 }
34. 数零壹 (20 分)
题目描述:
给定一串长度不超过 105 的字符串,本题要求你将其中所有英文字母的序号(字母 a-z 对应序号 1-26,不分大小写)相加,得到整数 N,然后再分析一下 N 的二进制表示中有多少 0、多少 1。例如给定字符串 PAT (Basic)
,其字母序号之和为:16+1+20+2+1+19+9+3=71,而 71 的二进制是 1000111,即有 3 个 0、4 个 1。
输入格式:
输入在一行中给出长度不超过 105、以回车结束的字符串。
输出格式:
在一行中先后输出 0 的个数和 1 的个数,其间以空格分隔。
输入样例:
PAT (Basic)
输出样例:
3 4
解题思路:
首先看完题目之后,按着题目意思来吧,先输入一个字符串,然后遍历这个字符串判断其中的字符是不是字母,若是字母,把它转换成小写再去求它在字母表中的序号,将这个序号累加到sum。因为二进制只有0和1,所以没必要建一个map来存放0和1的个数,直接用数组吧,通过memset()函数对数组中的元素进行初始化。然后直接用sum对2求余和整除来转换二进制就行了,最后输出0和1的个数。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 string s; 7 getline(cin,s); 8 int sum = 0; 9 for (int i = 0; i < s.length(); i++) 10 { 11 if(isalpha(s[i])) //判断是不是字母 12 { 13 sum += tolower(s[i])-'a'+1; //把字母全转成小写并求得在字母表中的序号 14 } 15 } 16 int a[2]; //因为只有0和1俩个数,所以没必要用map 17 memset(a,0,sizeof(a)); //将数组a默认初始值全设置为0 18 while(sum>0) 19 { 20 a[sum%2]++; 21 sum /= 2; 22 } 23 cout << a[0] << " " << a[1] << endl; 24 return 0; 25 }
35.害死人不偿命的(3n+1)猜想 (15 分)
题目描述:
卡拉兹(Callatz)猜想:
对任何一个正整数 n,如果它是偶数,那么把它砍掉一半;如果它是奇数,那么把 (3n+1) 砍掉一半。这样一直反复砍下去,最后一定在某一步得到 n=1。卡拉兹在 1950 年的世界数学家大会上公布了这个猜想,传说当时耶鲁大学师生齐动员,拼命想证明这个貌似很傻很天真的命题,结果闹得学生们无心学业,一心只证 (3n+1),以至于有人说这是一个阴谋,卡拉兹是在蓄意延缓美国数学界教学与科研的进展……
我们今天的题目不是证明卡拉兹猜想,而是对给定的任一不超过 1000 的正整数 n,简单地数一下,需要多少步(砍几下)才能得到 n=1?
输入格式:
每个测试输入包含 1 个测试用例,即给出正整数 n 的值。
输出格式:
输出从 n 计算到 1 需要的步数。
输入样例:
3
输出样例:
5
解题思路:
看完题就知道这是一道水题,直接判断n的奇偶性,若n为偶数,n=n/2,若n为奇数就n=(3*n+1)/2,每次对n进行赋值的时候,计数器count++就行了,最后输出的count就是结果。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int n; 7 cin >> n; 8 int count = 0; //用来计算从n到1需要的步数 9 while(n!=1) 10 { 11 if(n%2==0) //若n是偶数,则砍掉一半 12 { 13 n /= 2; 14 count++; 15 } 16 else //若n是奇数,则砍掉(3n+1)的一半 17 { 18 n = (3*n+1)/2; 19 count++; 20 } 21 } 22 cout << count << endl; 23 return 0; 24 }
36.C语言竞赛 (20 分)
题目描述:
C 语言竞赛是浙江大学计算机学院主持的一个欢乐的竞赛。既然竞赛主旨是为了好玩,颁奖规则也就制定得很滑稽:
- 0、冠军将赢得一份“神秘大奖”(比如很巨大的一本学生研究论文集……)。
- 1、排名为素数的学生将赢得最好的奖品 —— 小黄人玩偶!
- 2、其他人将得到巧克力。
给定比赛的最终排名以及一系列参赛者的 ID,你要给出这些参赛者应该获得的奖品。
输入格式:
输入第一行给出一个正整数 N(≤104),是参赛者人数。随后 N 行给出最终排名,每行按排名顺序给出一位参赛者的 ID(4 位数字组成)。接下来给出一个正整数 K 以及 K 个需要查询的 ID。
输出格式:
对每个要查询的 ID,在一行中输出 ID: 奖品
,其中奖品或者是 Mystery Award
(神秘大奖)、或者是 Minion
(小黄人)、或者是 Chocolate
(巧克力)。如果所查 ID 根本不在排名里,打印 Are you kidding?
(耍我呢?)。如果该 ID 已经查过了(即奖品已经领过了),打印 ID: Checked
(不能多吃多占)。
输入样例:
6 1111 6666 8888 1234 5555 0001 6 8888 0001 1111 2222 8888 2222
输出样例:
8888: Minion 0001: Chocolate 1111: Mystery Award 2222: Are you kidding? 8888: Checked 2222: Are you kidding?
解题思路:
首先自定义函数isPrime是肯定得有的,然后建立第一个map,map的key和value分别存放ID和排名,完成ID和排名的输入之后,再建立第二个map,map的key和value分别存放ID和是否领取了奖品(0为未领取,1为已领取)。接着是发放奖品,按题意来就行了,①排名第一的赢得一份“神秘大奖”;②排名为素数的学生将赢得最好的奖品 —— 小黄人玩偶;③其他人将得到巧克力。若奖品已被领取就输出"Checked";④如果输入的ID没有再排名里面,就输出"Are you kidding?",你在逗我吗?
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 bool isPrime(int n) 5 { 6 if(n<=1) return false; 7 for(int i=2;i<=sqrt(n);i++) 8 { 9 if(n%i==0) 10 { 11 return false; 12 } 13 } 14 return true; 15 } 16 17 int main() 18 { 19 int n; 20 cin >> n; 21 map<string,int> m; //key和value分别存放ID和排名 22 for (int i = 0; i < n; i++) 23 { 24 string temp; 25 cin >> temp; 26 m[temp] = i+1; //记录ID和排名 27 } 28 int k; 29 cin >> k; 30 map<string,int> flag; //判断奖品是否已被领取,1为被领取 31 for (int i = 0; i < k; i++) 32 { 33 string temp,award; 34 cin >> temp; 35 if(m[temp]!=0) 36 { 37 if(m[temp] == 1) //冠军将赢得一份“神秘大奖” 38 { 39 if(flag[temp] == 0) //若学生的奖品还未被领取 40 { 41 award = "Mystery Award"; 42 flag[temp] = 1; //领完奖之后记得标记 43 } 44 else 45 { 46 award = "Checked"; 47 } 48 } 49 else if(isPrime(m[temp])) //排名为素数的学生将赢得最好的奖品 —— 小黄人玩偶! 50 { 51 if(flag[temp] == 0) 52 { 53 award = "Minion"; 54 flag[temp] = 1; 55 } 56 else 57 { 58 award = "Checked"; 59 } 60 } 61 else //其他人将得到巧克力 62 { 63 if(flag[temp] == 0) 64 { 65 award = "Chocolate"; 66 flag[temp] = 1; 67 } 68 else 69 { 70 award = "Checked"; 71 } 72 } 73 cout << temp << ": " << award << endl; 74 } 75 else 76 { 77 cout << temp << ": Are you kidding?" << endl; 78 } 79 } 80 return 0; 81 }
37. 微博转发抽奖 (20 分)
题目描述:
小明 PAT 考了满分,高兴之余决定发起微博转发抽奖活动,从转发的网友中按顺序每隔 N 个人就发出一个红包。请你编写程序帮助他确定中奖名单。
输入格式:
输入第一行给出三个正整数 M(≤ 1000)、N 和 S,分别是转发的总量、小明决定的中奖间隔、以及第一位中奖者的序号(编号从 1 开始)。随后 M 行,顺序给出转发微博的网友的昵称(不超过 20 个字符、不包含空格回车的非空字符串)。
注意:可能有人转发多次,但不能中奖多次。所以如果处于当前中奖位置的网友已经中过奖,则跳过他顺次取下一位。
输出格式:
按照输入的顺序输出中奖名单,每个昵称占一行。如果没有人中奖,则输出 Keep going...
。
输入样例 1:
9 3 2 Imgonnawin! PickMe PickMeMeMeee LookHere Imgonnawin! TryAgainAgain TryAgainAgain Imgonnawin! TryAgainAgain
输出样例 1:
PickMe Imgonnawin! TryAgainAgain
输入样例 2:
2 3 5 Imgonnawin! PickMe
输出样例 2:
Keep going...
解题思路:
建立一个字符串队列queue用来存入中奖者的昵称,建立一个中奖者名单map,这个操作看上去是重复的,写到后面才会发现这俩者的用处。立一个flag用来记录是否有人中奖,true为没人中奖。用for循环遍历,如果这是中奖者,先判断他在不在map里,若不在map里,就把它放入map同时入队,若在map里,就跳过他顺次取下一位(S++;continue)。每次抽完中奖者之后,中将序号需要加上一个中奖间隔。最后把队列从队首开始根据“先进先出”的规则进行输出。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int M,N,S; //M为转发的总量,N为小明决定的中奖间隔,S是第一位中奖者的序号 7 cin >> M >> N >> S; 8 queue<string> q; //字符串型队列 9 map<string, int> m; //中奖名单 10 bool flag = true; //flag用来记录是否有人中奖,true为没人中奖 11 for (int i = 1; i <= M; i++) 12 { 13 string temp; 14 cin >> temp; 15 if(i==S) //中奖者 16 { 17 flag = false; 18 if(m[temp]==0) //若中奖者未在中奖名单中 19 { 20 m[temp]++; //把中奖者记录在中奖名单 21 q.push(temp); //入队 22 } 23 else //若中奖者出现在了中奖名单中,则跳过他顺次取下一位 24 { 25 S++; 26 continue; //直接进入下一次循环 27 } 28 S += N; //中奖者的间隔为N 29 } 30 } 31 while(!q.empty()) //把队列清空 32 { 33 cout << q.front() << endl; //输出队首字符串 34 q.pop(); //删除队首字符串 35 } 36 if(flag) //flag为true表示无人中奖,输出"Keep going..." 37 { 38 cout << "Keep going..." << endl; 39 } 40 return 0; 41 }
38. 编程团体赛 (20 分)
题目描述:
编程团体赛的规则为:每个参赛队由若干队员组成;所有队员独立比赛;参赛队的成绩为所有队员的成绩和;成绩最高的队获胜。
现给定所有队员的比赛成绩,请你编写程序找出冠军队。
输入格式:
输入第一行给出一个正整数 N(≤104),即所有参赛队员总数。随后 N 行,每行给出一位队员的成绩,格式为:队伍编号-队员编号 成绩
,其中队伍编号
为 1 到 1000 的正整数,队员编号
为 1 到 10 的正整数,成绩
为 0 到 100 的整数。
输出格式:
在一行中输出冠军队的编号和总成绩,其间以一个空格分隔。注意:题目保证冠军队是唯一的。
输入样例:
6 3-10 99 11-5 87 102-1 0 102-3 100 11-9 89 3-2 61
输出样例:
11 176
解题思路:
建立一个结构体,它由3个变量组成,队伍编号,队员编号和成绩(其实这个队员编号只是一个干扰项)。建立一个map,map的key是队伍的编号,value是队伍的总得分。max用来记录得分最多的那队的总得分,maxteam用来记录得分最多那对的队伍编号。输出结果这题也就解出来了。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 struct team 5 { 6 int ID; 7 int personnum; 8 int score; 9 }; 10 11 int main() 12 { 13 int n; 14 cin >> n; 15 vector<struct team> v(n); 16 map<int,int> m; //map的key是队伍的编号,value是队伍的总得分 17 int max = 0; //得分最多的那队的得分 18 int maxteam; //得分最多的那队的编号 19 for (int i = 0; i < n; i++) 20 { 21 scanf("%d-%d %d", &v[i].ID, &v[i].personnum, &v[i].score); 22 m[v[i].ID] += v[i].score; 23 if (m[v[i].ID] >max) 24 { 25 max = m[v[i].ID]; 26 maxteam = v[i].ID; 27 } 28 } 29 cout << maxteam << " " << max; 30 return 0; 31 }
39. 字符串压缩与解压 (20 分)
题目描述:
文本压缩有很多种方法,这里我们只考虑最简单的一种:把由相同字符组成的一个连续的片段用这个字符和片段中含有这个字符的个数来表示。例如 ccccc
就用 5c
来表示。如果字符没有重复,就原样输出。例如 aba
压缩后仍然是 aba
。
解压方法就是反过来,把形如 5c
这样的表示恢复为 ccccc
。
本题需要你根据压缩或解压的要求,对给定字符串进行处理。这里我们简单地假设原始字符串是完全由英文字母和空格组成的非空字符串。
输入格式:
输入第一行给出一个字符,如果是 C
就表示下面的字符串需要被压缩;如果是 D
就表示下面的字符串需要被解压。第二行给出需要被压缩或解压的不超过 1000 个字符的字符串,以回车结尾。题目保证字符重复个数在整型范围内,且输出文件不超过 1MB。
输出格式:
根据要求压缩或解压字符串,并在一行中输出结果。
输入样例 1:
C TTTTThhiiiis isssss a tesssst CAaaa as
输出样例 1:
5T2h4is i5s a3 te4st CA3a as
输入样例 2:
D 5T2h4is i5s a3 te4st CA3a as10Z
输出样例 2:
TTTTThhiiiis isssss a tesssst CAaaa asZZZZZZZZZZ
解题思路:
这应该算是复杂一点的水题吧,思路写在注释中。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 void compression(string s); //压缩字符串 5 void decompression(string s); //解压字符串 6 7 int main() 8 { 9 char ch; 10 cin >> ch; //输入一个字符 11 getchar(); //吃回车 12 string s; 13 getline(cin,s); //获取一行字符串 14 switch(ch) //判断是压缩还是解压缩 15 { 16 case 'C': compression(s); break; //压缩字符串 17 case 'D': decompression(s); break; //解压字符串 18 default: break; 19 } 20 return 0; 21 } 22 23 void compression(string s) //压缩字符串 24 { 25 for(int i=0;i<s.length();i++) //遍历字符串 26 { 27 int Count=0; //用来记录重复字符数量 28 while(s[i]==s[i+1]) //判断是不是字符串中的重复字符 29 { 30 i++; 31 Count++; 32 } 33 if(Count!=0) 34 { 35 cout << Count+1; //压缩后的形式,先输出重复字符的个数 36 } 37 cout << s[i]; //再输出重复字符 38 } 39 } 40 41 void decompression(string s) //解压字符串 42 { 43 for(int i=0;i<s.length();i++) //遍历字符串 44 { 45 int Count=0; 46 while(s[i]>='0'&&s[i]<='9') 47 { 48 Count = Count*10 + s[i]-'0'; //统计被压缩字符串的个数,可能是俩位数 49 i++; 50 } 51 for(int j=0;j<Count;j++) 52 { 53 cout << s[i]; //输出被压缩的字符 54 } 55 if(Count==0) //如果不是被压缩的字符则直接输出 56 { 57 cout << s[i]; 58 } 59 } 60 }
40.部分A+B (15 分)
题目描述:
正整数 A 的“DA(为 1 位整数)部分”定义为由 A 中所有 DA 组成的新整数 PA。例如:给定 A=3862767,DA=6,则 A 的“6 部分”PA 是 66,因为 A 中有 2 个 6。
现给定 A、DA、B、DB,请编写程序计算 PA+PB。
输入格式:
输入在一行中依次给出 A、DA、B、DB,中间以空格分隔,其中 0<A,B<1010。
输出格式:
在一行中输出 PA+PB 的值。
输入样例 1:
3862767 6 13530293 3
输出样例 1:
399
输入样例 2:
3862767 1 13530293 8
输出样例 2:
0
解题思路:
这题破天荒地写了三段代码。其实这三种解法思路都差不多,就是细节处理有区别,算了,下面还是把它们称之为思路吧。
Python思路:看完这道题之后就觉得Python大法好啊,俩行代码AC。第一行代码不需要解释,第二行代码可以分解成三个步骤来理解:①调用字符串中的count函数得到字符串A中子字符Da的数量,用这个数量乘以字符Da,就可以得到题目中的Pa;②同理,调用字符串中的count函数得到字符串B中子字符Db的数量,用这个数量乘以字符Db,就可以得到题目中的Pb;③把Pa和Pb强制转换成int型再相加就能得到最后的结果。
C++思路一:C++的第一种求解思路,跟Python的思路大致相同。这里解释一下string型强制转换成int型的代码,atoi(Pa.c_str())。由于函数原型是int atoi(const char *nptr),所以在调用的过程中应该先用c_str()把string型转换成char*的字符串,再通过atoi来转换成int型。
C++思路二:C++的第二种求解思路,这段代码中Pa和Pb都是int型,无需像前俩种解法一样进行string型到int型的强制转换,直接在遍历字符串的同时完成Pa和Pb的累加。
Python AC代码:
1 A,Da,B,Db = input().split() 2 print(int(A.count(Da)*Da or "0") + int(B.count(Db)*Db or "0"))
C++ AC代码一:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 string A,B; 7 char Da,Db; 8 cin >> A >> Da >> B >> Db; 9 string Pa="",Pb=""; 10 for(int i=0;i<A.length();i++) 11 { 12 if(A[i] == Da) 13 { 14 Pa += Da; 15 } 16 } 17 for(int i=0;i<B.length();i++) 18 { 19 if(B[i] == Db) 20 { 21 Pb += Db; 22 } 23 } 24 int sum = atoi(Pa.c_str()) + atoi(Pb.c_str()); //string型强制转换成int型再相加 25 cout << sum << endl; 26 return 0; 27 }
C++ AC代码二:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 string A,B; 7 char Da,Db; 8 cin >> A >> Da >> B >> Db; 9 int Pa = 0,Pb = 0; 10 for(int i=0;i<A.length();i++) 11 { 12 if(A[i] == Da) 13 { 14 Pa = Pa*10 + (Da-'0'); 15 } 16 } 17 for(int i=0;i<B.length();i++) 18 { 19 if(B[i] == Db) 20 { 21 Pb = Pb*10 + (Db-'0'); 22 } 23 } 24 int sum = Pa + Pb; 25 cout << sum << endl; 26 return 0; 27 }
41. 完美数列 (25 分)
题目描述:
给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 M≤mp,则称这个数列是完美数列。
现在给定参数 p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列。
输入格式:
输入第一行给出两个正整数 N 和 p,其中 N(≤105)是输入的正整数的个数,p(≤109)是给定的参数。第二行给出 N 个正整数,每个数不超过 109。
输出格式:
在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。
输入样例:
10 8 2 3 20 4 5 1 6 7 8 9
输出样例:
8
解题思路:
这题oj.hbu.cn上面写过,见注释。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int n; //输入的正整数个数 7 long long p; //给定的参数 8 cin >> n >> p; 9 long long a[n]; 10 for (int i = 0; i < n; i++) 11 { 12 cin >> a[i]; 13 } 14 sort(a,a+n); //对数组进行升序排序 15 int count = 1; //用来记录最长的完美数列长度 16 for (int i = 0; i < n; i++) //把a[i]作为最小值 17 { 18 for (int j = i+count; j < n; j++) //把a[j]作为最大值 19 { 20 if(a[j] <= a[i]*p) //判断最大值M和最小值m是否满足M<=m*p 21 { 22 count = max(count,j-i+1); //如果数列的个数大于最长的,则更新数列长度 23 } 24 else 25 { 26 break; 27 } 28 } 29 } 30 cout << count << endl; 31 return 0; 32 }
42. 说反话 (20 分)
题目描述:
给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。
输入格式:
测试输入包含一个测试用例,在一行内给出总长度不超过 80 的字符串。字符串由若干单词和若干空格组成,其中单词是由英文字母(大小写有区分)组成的字符串,单词之间用 1 个空格分开,输入保证句子末尾没有多余的空格。
输出格式:
每个测试用例的输出占一行,输出倒序后的句子。
输入样例:
Hello World Here I Come
输出样例:
Come I Here World Hello
解题思路:
看完题目之后就可以无脑用Python了。分步骤讲解一下吧,input().split()将输入的一行字符串以空格为分隔符添加到一个列表temp里," ".join(temp[::-1])是把列表temp中的元素倒序添加到一个以空格为分隔符的字符串里,这个字符串也就是最后的结果。
AC代码:
print(" ".join(input().split()[::-1]))
43.组合数的和 (15 分)
题目描述:
给定 N 个非 0 的个位数字,用其中任意 2 个数字都可以组合成 1 个 2 位的数字。要求所有可能组合出来的 2 位数字的和。例如给定 2、5、8,则可以组合出:25、28、52、58、82、85,它们的和为330。
输入格式:
输入在第一行中给出 N(1 < N < 10),随后一行给出 N 个不同的非 0 个位数字。数字间以空格分隔。
输出格式:
输出所有可能组合出来的2位数字的和。
输入样例:
3 2 8 5
输出样例:
330
解题思路:
这是一道水题,送分题,无脑for循环组合出所有可能组合出来的2位数字,然后对他们累加求和就行了。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int n; 7 cin >> n; 8 int a[n]; 9 for (int i = 0; i < n; i++) 10 { 11 cin >> a[i]; 12 } 13 int sum = 0; 14 //组合出所有可能组合出来的2位数字,并累加和 15 for (int i = 0; i < n; i++) 16 { 17 for (int j = 0; j < n; j++) 18 { 19 if(i!=j) 20 { 21 sum += a[i]*10+a[j]; 22 } 23 } 24 } 25 cout << sum << endl; 26 return 0; 27 }
44. 数字加密 (20 分)
题目描述:
本题要求实现一种数字加密方法。首先固定一个加密用正整数 A,对任一正整数 B,将其每 1 位数字与 A 的对应位置上的数字进行以下运算:对奇数位,对应位的数字相加后对 13 取余——这里用 J 代表 10、Q 代表 11、K 代表 12;对偶数位,用 B 的数字减去 A 的数字,若结果为负数,则再加 10。这里令个位为第 1 位。
输入格式:
输入在一行中依次给出 A 和 B,均为不超过 100 位的正整数,其间以空格分隔。
输出格式:
在一行中输出加密后的结果。
输入样例:
1234567 368782971
输出样例:
3695Q8118
解题思路:
我不晓得为啥第一次写出来的代码提交之后,4个测试用例AC,2个测试用例显示段错误。在我各种求助之后,发现题目中并没有表明字符串b一定大于字符串a。感谢我的某位巨佬同学把这个bug修复了。她举了个例子,当输入"12 1",即a=12 b=1时,我的代码输出结果是3,而根据题意可知正确答案应该是93。具体的修改方法是:如果字符串a的长度大于字符串b的长度,则在字符串b的前面补0,一开始就把b.length()-a.length()个0推入B栈来完成补0操作。其他地方完全不用改变。哈哈哈哈哈 提交之后发现6个测试用例全部AC。
AC代码:部分AC部分段错误代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 string a,b; 7 cin >> a >> b; 8 stack<int> A; 9 stack<int> B; 10 for (int i = 0; i < a.length(); i++) 11 { 12 A.push(a[i]-'0'); 13 } 14 for (int i = 0; i < b.length(); i++) 15 { 16 B.push(b[i]-'0'); 17 } 18 int count = 1; //位数 19 stack<string> result; 20 while(!A.empty()) 21 { 22 if(count%2==0) //对于偶数位 23 { 24 int temp = B.top()-A.top(); //用B的数字减去A的数字 25 if(temp < 0) //若结果为负数 26 { 27 temp += 10; //再加10 28 } 29 result.push(to_string(temp)); //压入栈中 30 } 31 else //对于奇数位 32 { 33 int temp = (B.top()+A.top())%13; //对应位的数字相加后对13取余 34 switch(temp) 35 { 36 case 10: result.push("J"); break; 37 case 11: result.push("Q"); break; 38 case 12: result.push("K"); break; 39 default: result.push(to_string(temp)); break; 40 } 41 } 42 count++; 43 A.pop(); //删除A的栈顶元素 44 B.pop(); //删除B的栈顶元素 45 } 46 while(!B.empty()) //若B中还有多余的元素 47 { 48 result.push(to_string(B.top())); 49 B.pop(); 50 } 51 while(!result.empty()) 52 { 53 cout << result.top(); 54 result.pop(); 55 } 56 return 0; 57 }
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 string a,b; 7 cin >> a >> b; 8 stack<int> A; 9 stack<int> B; 10 int lena = a.length(); //字符串a的长度 11 int lenb = b.length(); //字符串b的长度 12 if(lenb < lena) //若字符串a比字符串b长 13 { 14 for (int i = 0; i < lena-lenb; i++) 15 { 16 B.push(0); //将字符串b的开头进行补0,根据堆栈先进后出的特点,先把0入栈 17 } 18 } 19 for (int i = 0; i < lena; i++) 20 { 21 A.push(a[i]-'0'); 22 } 23 for (int i = 0; i < lenb; i++) 24 { 25 B.push(b[i]-'0'); 26 } 27 int count = 1; //位数 28 stack<string> result; //加密后的结果 29 while(!A.empty()) //无论a长还是b长,加密的位数按照A的长度来 30 { 31 if(count%2==0) //对于偶数位 32 { 33 int temp = B.top()-A.top(); //用B的数字减去A的数字 34 if(temp < 0) //若结果为负数 35 { 36 temp += 10; //再加10 37 } 38 result.push(to_string(temp)); //压入栈中 39 } 40 else //对于奇数位 41 { 42 int temp = (B.top()+A.top())%13; //对应位的数字相加后对13取余 43 switch(temp) 44 { 45 case 10: result.push("J"); break; 46 case 11: result.push("Q"); break; 47 case 12: result.push("K"); break; 48 default: result.push(to_string(temp)); break; //把int型的数字变成string型 49 } 50 } 51 count++; 52 A.pop(); //删除A的栈顶元素 53 B.pop(); //删除B的栈顶元素 54 } 55 while(!B.empty()) //若B中还有多余的元素,则把它们全部推入栈中 56 { 57 result.push(to_string(B.top())); 58 B.pop(); 59 } 60 while(!result.empty()) //清仓大甩卖 61 { 62 cout << result.top(); //输出加密后的结果 63 result.pop(); 64 } 65 return 0; 66 }
45. 打印沙漏 (20 分)
题目描述:
本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印
*****
***
*
***
*****
所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。
给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。
输入格式:
输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。
输出格式:
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
输入样例:
19 *
输出样例:
***** *** * *** ***** 2
解题思路:
先大致按照题目给的方向写,然后一点一点试错,最后AC。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int n; 7 char c; 8 cin >> n >> c; 9 int m = sqrt((n+1)/2); //沙漏单边的层数 10 //打印沙漏的上部分 11 int count = 0; //用来记录沙粒的个数 12 for (int i = 0; i < m; i++) 13 { 14 for (int j = 0; j < i; j++) 15 { 16 cout << " "; 17 } 18 for (int j = 2*(m-i)-1; j > 0; j--) 19 { 20 cout << c; 21 count++; 22 } 23 cout << endl; 24 } 25 //打印沙漏的下部分 26 for (int i = 1; i < m; i++) 27 { 28 for (int j = 0; j < m-i-1; j++) 29 { 30 cout << " "; 31 } 32 for (int j = 0; j < 2*i+1; j++) 33 { 34 cout << c; 35 count++; 36 } 37 cout << endl; 38 } 39 cout << n-count << endl; 40 return 0; 41 }
46. 一元多项式求导 (25 分)
题目描述:
设计函数求一元多项式的导数。(注:xn(n为整数)的一阶导数为nxn−1。)
输入格式:
以指数递降方式输入多项式非零项系数和指数(绝对值均为不超过 1000 的整数)。数字间以空格分隔。
输出格式:
以与输入相同的格式输出导数多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。注意“零多项式”的指数和系数都是 0,但是表示为 0 0
。
输入样例:
3 4 -5 2 6 1 -2 0
输出样例:
12 3 -10 1 6 0
解题思路:
我感觉这题不值25分,算得上是25分题里的水题吧。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int a,n; 7 bool flag = false; 8 while(cin >> a >> n) 9 { 10 if(a*n) 11 { 12 if(flag) 13 { 14 cout << " "; 15 } 16 flag = true; 17 cout << a*n << " " << n-1; 18 } 19 } 20 if(!flag) 21 { 22 cout << "0 0"; 23 } 24 return 0; 25 }
47. 检查密码 (15 分)
题目描述:
本题要求你帮助某网站的用户注册模块写一个密码合法性检查的小功能。该网站要求用户设置的密码必须由不少于6个字符组成,并且只能有英文字母、数字和小数点 .
,还必须既有字母也有数字。
输入格式:
输入第一行给出一个正整数 N(≤ 100),随后 N 行,每行给出一个用户设置的密码,为不超过 80 个字符的非空字符串,以回车结束。
输出格式:
对每个用户的密码,在一行中输出系统反馈信息,分以下5种:
- 如果密码合法,输出
Your password is wan mei.
; - 如果密码太短,不论合法与否,都输出
Your password is tai duan le.
; - 如果密码长度合法,但存在不合法字符,则输出
Your password is tai luan le.
; - 如果密码长度合法,但只有字母没有数字,则输出
Your password needs shu zi.
; - 如果密码长度合法,但只有数字没有字母,则输出
Your password needs zi mu.
。
输入样例:
5 123s zheshi.wodepw 1234.5678 WanMei23333 pass*word.6
输出样例:
Your password is tai duan le. Your password needs shu zi. Your password needs zi mu. Your password is wan mei. Your password is tai luan le.
解题思路:
哎呀呀呀,没时间了,马上考试了,解析见注释吧
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int N; 7 cin >> N; 8 getchar(); 9 while(N--) 10 { 11 string temp; 12 getline(cin,temp); 13 int len = temp.length(); 14 if(len < 6) //如果密码少于6位,输出太短了 15 { 16 cout << "Your password is tai duan le." << endl; 17 } 18 else //如果密码长度合法 19 { 20 int zm = 0, sz = 0, dot = 0, qt = 0; //分别记录字母、数字、点和其他字符的个数 21 for(int i = 0;i < len;i++) 22 { 23 if((temp[i]>='a'&&temp[i]<='z')||(temp[i]>='A'&&temp[i]<='Z')) //判断是否为字母 24 { 25 zm++; 26 } 27 else if(temp[i]>='0'&&temp[i]<='9') //判断是否为数字 28 { 29 sz++; 30 } 31 else if(temp[i] == '.') //判断是否有小数点 32 { 33 dot++; 34 } 35 else //不是字母数字小数点就是其他字符了 36 { 37 qt++; 38 } 39 } 40 if(qt) //若其他字符的个数不为0 41 { 42 cout << "Your password is tai luan le." << endl; 43 } 44 else if(sz==0) //若没有数字字符 45 { 46 cout << "Your password needs shu zi." << endl; 47 } 48 else if(zm==0) //若没有字母字符 49 { 50 cout << "Your password needs zi mu." << endl; 51 } 52 else //完美 53 { 54 cout << "Your password is wan mei." << endl; 55 } 56 } 57 } 58 return 0; 59 }
48. 结绳 (25 分)
题目描述:
给定一段一段的绳子,你需要把它们串成一条绳。每次串连的时候,是把两段绳子对折,再如下图所示套接在一起。这样得到的绳子又被当成是另一段绳子,可以再次对折去跟另一段绳子串连。每次串连后,原来两段绳子的长度就会减半。
给定 N 段绳子的长度,你需要找出它们能串成的绳子的最大长度。
输入格式:
每个输入包含 1 个测试用例。每个测试用例第 1 行给出正整数 N (2≤N≤104);第 2 行给出 N 个正整数,即原始绳段的长度,数字间以空格分隔。所有整数都不超过104。
输出格式:
在一行中输出能够串成的绳子的最大长度。结果向下取整,即取为不超过最大长度的最近整数。
输入样例:
8 10 15 12 3 4 13 1 15
输出样例:
14
解题思路:
哎呀呀呀,没时间了,马上考试了,解析见注释吧,每对折一次,长度就会减少一半,所以尽可能让较长的绳子少对折。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int N; 7 cin >> N; 8 int a[N]; 9 for (int i = 0; i < N; i++) 10 { 11 cin >> a[i]; 12 } 13 sort(a,a+N); //升序排序 14 //绳子每进行一次连接就要对折一次,长度就会减少一半,经可能让较长的绳子少对折 15 int ans = a[0]; 16 for (int i = 1; i < N; i++) 17 { 18 ans = (ans+a[i])/2; //把绳子进行串联 19 } 20 cout << ans << endl; 21 return 0; 22 }
49. 是否存在相等的差 (20 分)
题目描述:
给定 N 张卡片,正面分别写上 1、2、……、N,然后全部翻面,洗牌,在背面分别写上 1、2、……、N。将每张牌的正反两面数字相减(大减小),得到 N 个非负差值,其中是否存在相等的差?
输入格式:
输入第一行给出一个正整数 N(2 ≤ N ≤ 10 000),随后一行给出 1 到 N 的一个洗牌后的排列,第 i 个数表示正面写了 i 的那张卡片背面的数字。
输出格式:
按照“差值 重复次数”的格式从大到小输出重复的差值及其重复的次数,每行输出一个结果。
输入样例:
8 3 5 8 6 2 1 4 7
输出样例:
5 2 3 3 2 2
解题思路:
哎呀呀呀,没时间了,马上考试了,解析见注释吧,无脑map记录绝对差值。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 map<int,int,greater<int>> m; 7 //map的第三个参数compare(默认为less<int> 升序),降序需要改成greater<int> 8 int N; 9 cin >> N; 10 for (int i = 1; i <= N; i++) 11 { 12 int temp; 13 cin >> temp; //洗牌后的排列 14 m[abs(temp-i)]++; 15 } 16 for(auto it=m.begin();it!=m.end();it++) 17 { 18 if(it->second > 1) 19 { 20 cout << it->first << " " << it->second << endl; 21 } 22 } 23 /* 最后那个for循环换成for-each循环也可以AC,需要注意的是for-each循环中不能写it->first,需要改成it.first 24 for(auto it:m) 25 { 26 if(it.second > 1) 27 { 28 cout << it.first << " " << it.second << endl; 29 } 30 } 31 */ 32 return 0; 33 }
50. 三人行 (20 分)
题目描述:
子曰:“三人行,必有我师焉。择其善者而从之,其不善者而改之。”
本题给定甲、乙、丙三个人的能力值关系为:甲的能力值确定是 2 位正整数;把甲的能力值的 2 个数字调换位置就是乙的能力值;甲乙两人能力差是丙的能力值的 X 倍;乙的能力值是丙的 Y 倍。请你指出谁比你强应“从之”,谁比你弱应“改之”。
输入格式:
输入在一行中给出三个数,依次为:M(你自己的能力值)、X 和 Y。三个数字均为不超过 1000 的正整数。
输出格式:
在一行中首先输出甲的能力值,随后依次输出甲、乙、丙三人与你的关系:如果其比你强,输出 Cong
;平等则输出 Ping
;比你弱则输出 Gai
。其间以 1 个空格分隔,行首尾不得有多余空格。
注意:如果解不唯一,则以甲的最大解为准进行判断;如果解不存在,则输出 No Solution
。
输入样例 1:
48 3 7
输出样例 1:
48 Ping Cong Gai
输入样例 2:
48 11 6
输出样例 2:
No Solution
解题思路:
哎呀呀呀,没时间了,马上考试了,解析见注释吧,这题无脑for循环暴力破解。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 void Cmp(int m,double n); 5 6 int main() 7 { 8 int M,X,Y; //M是你的能力值,它是个2位的正整数 9 cin >> M >> X >> Y; 10 int A,B; //A是甲的能力值,B是乙的能力值 11 double C; //C是丙的能力值 12 //若解不唯一,则以甲的最大解为准,直接从大往小找 13 bool flag = false; 14 for (int i = 99; i > 9; i--) 15 { 16 B = i%10*10+i/10; //甲的能力值的2个数字调换位置就是乙的能力值 17 int temp = abs(i-B); //甲乙俩人的能力差 18 //乙的能力值是丙的Y倍,且甲乙俩人能力差是丙能力值的X倍 19 C = temp/double(X); 20 if(C*Y == B) 21 { 22 A = i; 23 flag = true; 24 break; 25 } 26 } 27 if(!flag) 28 { 29 cout << "No Solution" << endl; 30 } 31 else 32 { 33 cout << A; 34 Cmp(M,A); 35 Cmp(M,B); 36 Cmp(M,C); 37 } 38 return 0; 39 } 40 41 void Cmp(int m,double n) 42 { 43 if(m > n) 44 { 45 cout << " Gai"; //改 46 } 47 else if(m < n) 48 { 49 cout << " Cong"; //从 50 } 51 else 52 { 53 cout << " Ping"; //平 54 } 55 }
51. 数列的片段和 (20 分)
题目描述:
给定一个正数数列,我们可以从中截取任意的连续的几个数,称为片段。例如,给定数列 { 0.1, 0.2, 0.3, 0.4 },我们有 (0.1) (0.1, 0.2) (0.1, 0.2, 0.3) (0.1, 0.2, 0.3, 0.4) (0.2) (0.2, 0.3) (0.2, 0.3, 0.4) (0.3) (0.3, 0.4) (0.4) 这 10 个片段。
给定正整数数列,求出全部片段包含的所有的数之和。如本例中 10 个片段总和是 0.1 + 0.3 + 0.6 + 1.0 + 0.2 + 0.5 + 0.9 + 0.3 + 0.7 + 0.4 = 5.0。
输入格式:
输入第一行给出一个不超过 105 的正整数 N,表示数列中数的个数,第二行给出 N 个不超过 1.0 的正数,是数列中的数,其间以空格分隔。
输出格式:
在一行中输出该序列所有片段包含的数之和,精确到小数点后 2 位。
输入样例:
4 0.1 0.2 0.3 0.4
输出样例:
5.00
解题思路:
额,看完题目之后二话不说直接码代码对这题进行暴力破解,然而TLE了!找规律是不可找规律的,这辈子都只会暴力破解。每个数出现的次数 = (这个数左边数的数量+1) * (这个数右边数的数量+1)。N-i其实就是这个数右边数的数量(N-i-1)+1。
AC代码:TLE代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 ios::sync_with_stdio(false); //取消cin和stdin的同步 7 int N; 8 cin >> N; 9 double a[N]; 10 double sum = 0; //该序列中所有片段包含的数之和 11 for (int i = 0; i < N; i++) 12 { 13 cin >> a[i]; 14 sum += a[i]; //先把每个数单独组成的片段累加 15 } 16 for (int i = 0; i < N; i++) 17 { 18 double temp = a[i]; //求以a[i]为第一个数所组成的所有片段的累加和 19 for (int j = i+1; j < N; j++) 20 { 21 temp += a[j]; 22 sum += temp; 23 } 24 } 25 printf("%.2f ",sum); 26 return 0; 27 }
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 ios::sync_with_stdio(false); //取消cin和stdin的同步 7 int N; 8 cin >> N; 9 double sum = 0; //该序列中所有片段包含的数之和 10 for (int i = 0; i < N; i++) 11 { 12 double temp; 13 cin >> temp; 14 sum += (i+1)*temp*(N-i); //某个数的出现次数 =(这个数左边数的数量+1)*(位于这个数右边的数的数量+1) 15 } 16 printf("%.2f ",sum); 17 return 0; 18 }
52. 爱丁顿数 (25 分)
题目描述:
英国天文学家爱丁顿很喜欢骑车。据说他为了炫耀自己的骑车功力,还定义了一个“爱丁顿数” E ,即满足有 E 天骑车超过 E 英里的最大整数 E。据说爱丁顿自己的 E 等于87。
现给定某人 N 天的骑车距离,请你算出对应的爱丁顿数 E(≤N)。
输入格式:
输入第一行给出一个正整数 N (≤105),即连续骑车的天数;第二行给出 N 个非负整数,代表每天的骑车距离。
输出格式:
在一行中给出 N 天的爱丁顿数。
输入样例:
10 6 7 6 9 3 10 8 2 7 8
输出样例:
6
解题思路:
哎呀呀呀,没时间了,马上考试了,解析见注释吧。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 bool Cmp(int a,int b) 5 { 6 return a > b; 7 } 8 9 int main() 10 { 11 int n; 12 cin >> n; //n为连续骑车的天数 13 int a[n+1]; 14 for (int i = 1; i <= n; i++) 15 { 16 cin >> a[i]; //从第一天开始,每天的骑车距离 17 } 18 sort(a+1,a+n+1,Cmp); //对这n天的骑车距离从大到小排序 19 int E = 0; //爱丁顿数 20 int i = 1; 21 while(i<=n && a[i]>i) //E他的骑车距离超过E英里的最大整数E 22 { 23 E++; 24 i++; 25 } 26 cout << E << endl; 27 return 0; 28 }
53. 计算谱半径 (20 分)
题目描述:
在数学中,矩阵的“谱半径”是指其特征值的模集合的上确界。换言之,对于给定的 n 个复数空间的特征值 { a1+b1i,⋯,an+bni },它们的模为实部与虚部的平方和的开方,而“谱半径”就是最大模。
现在给定一些复数空间的特征值,请你计算并输出这些特征值的谱半径。
输入格式:
输入第一行给出正整数 N(≤ 10 000)是输入的特征值的个数。随后 N 行,每行给出 1 个特征值的实部和虚部,其间以空格分隔。注意:题目保证实部和虚部均为绝对值不超过 1000 的整数。
输出格式:
在一行中输出谱半径,四舍五入保留小数点后 2 位。
输入样例:
5 0 1 2 0 -1 0 3 3 0 -3
输出样例:
4.24
解题思路:
谱半径就是最大模,而模为实部与虚部的平方和的开方,要求谱半径只需要找出实部、虚部最大的平方和即可。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int n; 7 cin >> n; //输入的特征值的个数 8 double ans = 0; //最大模的平方 9 for (int i = 0; i < n; i++) 10 { 11 double a,b; 12 cin >> a >> b; 13 ans = max(a*a+b*b,ans); 14 } 15 printf("%.2lf ", sqrt(ans)); 16 return 0; 17 }
54. 我要通过! (20 分)
题目描述:
“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于 PAT 的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。
得到“答案正确”的条件是:
1.字符串中必须仅有 P
、 A
、 T
这三种字符,不可以包含其它字符
2.任意形如 xPATx
的字符串都可以获得“答案正确”,其中 x
或者是空字符串,或者是仅由字母 A
组成的字符串;
3.如果 aPbTc
是正确的,那么 aPbATca
也是正确的,其中 a
、 b
、 c
均或者是空字符串,或者是仅由字母 A
组成的字符串。
现在就请你为 PAT 写一个自动裁判程序,判定哪些字符串是可以获得“答案正确”的。
输入格式:
每个测试输入包含 1 个测试用例。第 1 行给出一个正整数 n (<10),是需要检测的字符串个数。接下来每个字符串占一行,字符串长度不超过 100,且不包含空格。
输出格式:
每个字符串的检测结果占一行,如果该字符串可以获得“答案正确”,则输出 YES
,否则输出 NO
。
输入样例:
8 PAT PAAT AAPATAA AAPAATAAAA xPATx PT Whatever APAAATAA
输出样例:
YES YES YES YES NO NO NO NO
解题思路:
额,看了若干遍题目之后发现字符串中只能有一个P一个T,A只要不为0就行了,随便放哪儿。有个条件就是必须满足P前面A的个数*P与T之间A的个数等于T后面A的个数,简单来说就是若P和T中间有n个A,则末尾就得加上n*(P前面A的数量)个A,P和T中间不能一个A都没有。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int n; 7 cin >> n; //需要检测的字符串个数 8 for (int i = 0; i < n; i++) 9 { 10 string temp; 11 cin >> temp; 12 int len = temp.length(); 13 bool flag = true; 14 map<char, int> m; 15 int indexP,indexT; //indexP和indexT分别记录P和T的所在下标 16 for (int j = 0; j < len; j++) 17 { 18 switch(temp[j]) 19 { 20 case 'P': m['P']++; indexP = j; break; 21 case 'A': m['A']++; break; 22 case 'T': m['T']++; indexT = j; break; 23 default : flag = false; break; //字符串中不可以包含其它字符 24 } 25 } 26 if(m['P']==0 || m['A']==0 || m['T']==0) //字符串中必须有P、A、T这三种字符 27 { 28 flag = false; 29 } 30 else if(m['P']>1 || m['T']>1) //P、T的数量都不能大于1 31 { 32 flag = false; 33 } 34 else 35 { 36 if(indexP*(indexT-indexP-1) != len-indexT-1) //题目中的第三个条件 37 //若P和T中间有n个A,则末尾就得加上n*(P前面A的数量)个A 38 //即P前面A的个数*P与T之间A的个数等于T后面A的个数 39 { 40 flag = false; 41 } 42 } 43 if(flag) 44 { 45 cout << "YES" << endl; 46 } 47 else 48 { 49 cout << "NO" << endl; 50 } 51 } 52 return 0; 53 }
55. 数组元素循环右移问题 (20 分)
题目描述:
一个数组A中存有N(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(≥0)个位置,即将A中的数据由(A0A1⋯AN−1)变换为(AN−M⋯AN−1A0A1⋯AN−M−1)(最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?
输入格式:
每个输入包含一个测试用例,第1行输入N(1≤N≤100)和M(≥0);第2行输入N个整数,之间用空格分隔。
输出格式:
在一行中输出循环右移M位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。
输入样例:
6 2 1 2 3 4 5 6
输出样例:
5 6 1 2 3 4
解题思路:
哎呀呀呀,没时间了,马上考试了,解析见注释吧。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 void Input(int a[], int n); //数组元素的输入 5 void RightMove(int a[], int n, int m); //数组元素循环右移 6 void Print(int a[], int n); //数组元素的输出 7 8 int main() 9 { 10 int n, m; 11 cin >> n >> m; 12 int a[n+m]; //防止出现下标越界 13 Input(a,n); 14 RightMove(a,n,m); 15 Print(a,n); 16 } 17 18 void Input(int a[], int n) //数组元素的输入 19 { 20 for(int i=0;i<n;i++) 21 { 22 cin >> a[i]; 23 } 24 } 25 26 void RightMove(int a[], int n, int m) //数组元素循环右移 27 { 28 m = m%n; 29 for (int i = n+m-1; i > m-1; i--) 30 { 31 a[i] = a[i-m]; 32 } 33 for (int i = 0; i < m; i++) 34 { 35 a[i] = a[n+i]; 36 } 37 } 38 39 void Print(int a[], int n) //数组元素的输出 40 { 41 int i; 42 for(i=0;i<n-1;i++) 43 { 44 cout << a[i] << " "; 45 } 46 cout << a[n-1]; 47 }
56. 复数乘法 (15 分)
题目描述:
复数可以写成 (A+Bi) 的常规形式,其中 A 是实部,B 是虚部,i 是虚数单位,满足 i2=−1;也可以写成极坐标下的指数形式 (R×e(Pi)),其中 R 是复数模,P 是辐角,i 是虚数单位,其等价于三角形式 (R(cos(P)+isin(P))。
现给定两个复数的 R 和 P,要求输出两数乘积的常规形式。
输入格式:
输入在一行中依次给出两个复数的 R1, P1, R2, P2,数字间以空格分隔。
输出格式:
在一行中按照 A+Bi
的格式输出两数乘积的常规形式,实部和虚部均保留 2 位小数。注意:如果 B
是负数,则应该写成 A-|B|i
的形式。
输入样例:
2.3 3.5 5.2 0.4
输出样例:
-8.68-8.23i
解题思路:
哎呀呀呀,没时间了,马上考试了,解析见注释吧。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 double R1,P1,R2,P2; 7 cin >> R1 >> P1 >> R2 >> P2; 8 /* 9 *在极坐标下,复数可用模长r与幅角θ表示为(r,θ)。 10 *对于复数a+bi,r=√(a²+b²),θ=arctan(b/a)。 11 *此时,复数相乘表现为幅角相加,模长相乘。 12 */ 13 double real = R1*R2*cos(P1+P2); 14 double imagine = R1*R2*sin(P1+P2); 15 if(real > -0.005 && real < 0.005) //real = 0 16 { 17 cout << "0.00"; 18 } 19 else 20 { 21 cout << setiosflags(ios::fixed) << setprecision(2) << real; 22 //cout小数点后保留2位有效数字,有点复杂,下面还是用printf吧 23 } 24 if(imagine > -0.005 && imagine < 0.005) //imagine = 0 25 { 26 cout << "+0.00i" << endl; //imagine=0时虚部要写成+0.00i 27 } 28 else if(imagine > 0) 29 { 30 printf("+%.2fi ", imagine); 31 } 32 else if(imagine < 0) 33 { 34 printf("%.2fi ", imagine); 35 } 36 return 0; 37 }
57. 德才论 (25 分)
题目描述:
宋代史学家司马光在《资治通鉴》中有一段著名的“德才论”:“是故才德全尽谓之圣人,才德兼亡谓之愚人,德胜才谓之君子,才胜德谓之小人。凡取人之术,苟不得圣人,君子而与之,与其得小人,不若得愚人。”
现给出一批考生的德才分数,请根据司马光的理论给出录取排名。
输入格式:
输入第一行给出 3 个正整数,分别为:N(≤105),即考生总数;L(≥60),为录取最低分数线,即德分和才分均不低于 L 的考生才有资格被考虑录取;H(<100),为优先录取线——德分和才分均不低于此线的被定义为“才德全尽”,此类考生按德才总分从高到低排序;才分不到但德分到线的一类考生属于“德胜才”,也按总分排序,但排在第一类考生之后;德才分均低于 H,但是德分不低于才分的考生属于“才德兼亡”但尚有“德胜才”者,按总分排序,但排在第二类考生之后;其他达到最低线 L 的考生也按总分排序,但排在第三类考生之后。
随后 N 行,每行给出一位考生的信息,包括:准考证号 德分 才分
,其中准考证号
为 8 位整数,德才分为区间 [0, 100] 内的整数。数字间以空格分隔。
输出格式:
输出第一行首先给出达到最低分数线的考生人数 M,随后 M 行,每行按照输入格式输出一位考生的信息,考生按输入中说明的规则从高到低排序。当某类考生中有多人总分相同时,按其德分降序排列;若德分也并列,则按准考证号的升序输出。
输入样例:
14 60 80 10000001 64 90 10000002 90 60 10000011 85 80 10000003 85 80 10000004 80 85 10000005 82 77 10000006 83 76 10000007 90 78 10000008 75 79 10000009 59 90 10000010 88 45 10000012 80 100 10000013 90 99 10000014 66 60
输出样例:
12 10000013 90 99 10000012 80 100 10000003 85 80 10000011 85 80 10000004 80 85 10000007 90 78 10000006 83 76 10000005 82 77 10000002 90 60 10000014 66 60 10000008 75 79 10000001 64 90
解题思路:
哎呀呀呀,没时间了,马上考试了,解析见注释吧。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 struct student 5 { 6 int ID; //准考证号 7 int de,cai,sum; //德分和才分,总分 8 int level; //考生类别 9 }; 10 11 bool Cmp(student a,student b) 12 { 13 if(a.level != b.level) 14 { 15 return a.level < b.level; 16 } 17 else if(a.sum != b.sum) 18 { 19 return a.sum > b.sum; //按照总分从高到低的顺序进行排序 20 } 21 else if(a.de != b.de) 22 { 23 return a.de > b.de; //总分相同时,按照德分降序排列 24 } 25 else 26 { 27 return a.ID < b.ID; //总分和德分都并列时,按准考证号的升序输出 28 } 29 } 30 int main() 31 { 32 ios::sync_with_stdio(false); 33 int N,L,H,M; 34 cin >> N >> L >> H; 35 M = N; 36 std::vector<student> v(N); 37 for(int i = 0; i < N; i++) 38 { 39 cin >> v[i].ID >> v[i].de >> v[i].cai; 40 v[i].sum=v[i].de+v[i].cai; 41 if(v[i].de<L ||v[i].cai<L) 42 { 43 M--; 44 v[i].level=5; 45 } 46 else 47 { 48 if(v[i].de>=H && v[i].cai>=H) 49 { 50 v[i].level = 1; //level=1说明考生 德分和才分都达到了优先录取线 51 } 52 else if(v[i].de>=H && v[i].cai<H) 53 { 54 v[i].level = 2; //level=2说明考生 德分胜才分,且德分达到了最优录取线,才分未达到最优录取线 55 } 56 else if(v[i].de>=v[i].cai) 57 { 58 v[i].level = 3; //level=3说明考生 德分胜才分,但德分未达到最优录取线 59 } 60 else 61 { 62 v[i].level = 4; //level=4说明考生 德分和才分都低于最优录取线,且德不胜才 63 } 64 } 65 } 66 sort(v.begin(),v.end(),Cmp); 67 cout << M << endl; 68 for(int i = 0; i < M; i++) 69 { 70 cout << v[i].ID << " " <<v[i].de << " " << v[i].cai << endl; 71 } 72 return 0; 73 }
58. 福尔摩斯的约会 (20 分)
题目描述:
大侦探福尔摩斯接到一张奇怪的字条:我们约会吧! 3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm
。大侦探很快就明白了,字条上奇怪的乱码实际上就是约会的时间星期四 14:04
,因为前面两字符串中第 1 对相同的大写英文字母(大小写有区分)是第 4 个字母 D
,代表星期四;第 2 对相同的字符是 E
,那是第 5 个英文字母,代表一天里的第 14 个钟头(于是一天的 0 点到 23 点由数字 0 到 9、以及大写字母 A
到 N
表示);后面两字符串第 1 对相同的英文字母 s
出现在第 4 个位置(从 0 开始计数)上,代表第 4 分钟。现给定两对字符串,请帮助福尔摩斯解码得到约会的时间。
输入格式:
输入在 4 行中分别给出 4 个非空、不包含空格、且长度不超过 60 的字符串。
输出格式:
在一行中输出约会的时间,格式为 DAY HH:MM
,其中 DAY
是某星期的 3 字符缩写,即 MON
表示星期一,TUE
表示星期二,WED
表示星期三,THU
表示星期四,FRI
表示星期五,SAT
表示星期六,SUN
表示星期日。题目输入保证每个测试存在唯一解。
输入样例:
3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm
输出样例:
THU 14:04
解题思路:
哎呀呀呀,没时间了,马上考试了,解析见注释吧。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 string week[] = {"MON","TUE","WED","THU","FRI","SAT","SUN"}; 7 string s[4]; 8 for (int i = 0; i < 4; i++) 9 { 10 cin >> s[i]; 11 } 12 bool flag = false; //判断是否能破解 13 for(int i=0;s[0][i]&&s[1][i];i++) 14 { 15 if(!flag && s[0][i]>='A' &&s[0][i]<='G' && s[0][i]==s[1][i]) //周一到周日对应A到G,通过前面两字符串中第1对相同的大写英文字母来破解星期 16 { 17 cout << week[s[0][i]-'A'] << " "; 18 flag = true; 19 continue; 20 } 21 22 if(flag && s[0][i]==s[1][i] && ( s[0][i]>='A' &&s[0][i]<='N' || isdigit(s[0][i])) ) //一天的0点到23点由数字0到9、以及大写字母A到N表示 23 { 24 if(isupper(s[0][i])) //A到N对应一天的10点到23点 25 { 26 cout<<s[0][i]-'A'+10<<":"; 27 } 28 if(isdigit(s[0][i])) //0到9就对应一天的0到9点 29 { 30 cout<<"0"<<s[0][i]-'0'<<":"; 31 } 32 break; 33 } 34 } 35 for(int i=0;s[2][i] && s[3][i];i++) 36 { 37 if( isalpha(s[2][i])&& s[2][i]==s[3][i]) //后面两字符串第1对相同的英文字母出现在哪个位置就代表约会的分钟是多少 38 { 39 printf("%02d ",i); 40 break; 41 } 42 } 43 return 0; 44 }
59. 在霍格沃茨找零钱 (20 分)
题目描述:
如果你是哈利·波特迷,你会知道魔法世界有它自己的货币系统 —— 就如海格告诉哈利的:“十七个银西可(Sickle)兑一个加隆(Galleon),二十九个纳特(Knut)兑一个西可,很容易。”现在,给定哈利应付的价钱 P 和他实付的钱 A,你的任务是写一个程序来计算他应该被找的零钱。
输入格式:
输入在 1 行中分别给出 P 和 A,格式为 Galleon.Sickle.Knut
,其间用 1 个空格分隔。这里 Galleon
是 [0, 107] 区间内的整数,Sickle
是 [0, 17) 区间内的整数,Knut
是 [0, 29) 区间内的整数。
输出格式:
在一行中用与输入同样的格式输出哈利应该被找的零钱。如果他没带够钱,那么输出的应该是负数。
输入样例 1:
10.16.27 14.1.28
输出样例 1:
3.2.1
输入样例 2:
14.1.28 10.16.27
输出样例 2:
-3.2.1
解题思路:
看完题目,脑子里冒出一句话“人生苦短,....”后半句不说了。直接无脑用Python,1~3行基操勿6,12行调用了divmod函数。python真的是蒂花之秀,它这个divmod()函数把除数和余数运算结果结合起来,返回一个包含商和余数的元组(a // b, a % b)。然后我把元组中的值直接赋给了列表C中的第0个和第1个元素。
AC代码:
1 l = input().split() 2 P = list(map(int,l[0].split('.'))) 3 A = list(map(int,l[1].split('.'))) 4 Psum = (P[0]*17+P[1])*29+P[2] #哈利应付的价钱为Psum 5 Asum = (A[0]*17+A[1])*29+A[2] #哈利实付的价钱为Asum 6 Csum = Asum-Psum #哈利应该被找的零钱为Csum 7 sign = "" 8 if Csum < 0: 9 sign = "-" 10 Csum = abs(Csum) 11 C = [0,0,0] 12 C[0],C[1] = divmod(Csum//29,17) 13 C[2] = Csum%29 14 print(sign+".".join(str(i) for i in C))
60. 继续(3n+1)猜想 (25 分)
题目描述:
卡拉兹(Callatz)猜想已经在1001中给出了描述。在这个题目里,情况稍微有些复杂。
当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数。例如对 n=3 进行验证的时候,我们需要计算 3、5、8、4、2、1,则当我们对 n=5、8、4、2 进行验证的时候,就可以直接判定卡拉兹猜想的真伪,而不需要重复计算,因为这 4 个数已经在验证3的时候遇到过了,我们称 5、8、4、2 是被 3“覆盖”的数。我们称一个数列中的某个数 n 为“关键数”,如果 n 不能被数列中的其他数字所覆盖。
现在给定一系列待验证的数字,我们只需要验证其中的几个关键数,就可以不必再重复验证余下的数字。你的任务就是找出这些关键数字,并按从大到小的顺序输出它们。
输入格式:
每个测试输入包含 1 个测试用例,第 1 行给出一个正整数 K (<100),第 2 行给出 K 个互不相同的待验证的正整数 n (1<n≤100)的值,数字间用空格隔开。
输出格式:
每个测试用例的输出占一行,按从大到小的顺序输出关键数字。数字间用 1 个空格隔开,但一行中最后一个数字后没有空格。
输入样例:
6 3 5 6 7 8 11
输出样例:
7 6
解题思路:
首先,肯定要写出来(3n+1)猜想那题。用一个初始化全为true的bool型的数组用来记录所在下标能不能被其他的数覆盖,在输入的同时进行(3n+1)猜想,把(3n+1)猜想中所有出现过的数标记为false。输入结束后,将输入的数据中flag仍为true的元素放入一个vector中。最后对vector进行降序排序输出即可。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 bool Cmp(int a,int b) 5 { 6 return a > b; 7 } 8 9 int main() 10 { 11 bool flag[10000]; //若某个下标的flag为true,则说明这个数不能被其他的数覆盖 12 memset(flag,true,sizeof(flag)); //世界是美好的,先把flag全部初始化为true 13 int K; 14 cin >> K; 15 int a[K]; 16 for (int i = 0; i < K; i++) 17 { 18 cin >> a[i]; 19 int n = a[i]; 20 while(n != 1) //(3n+1)猜想最后得到的是1 21 { 22 if(n%2 == 0) //若n是偶数,则砍掉一半 23 { 24 n /= 2; 25 flag[n] = false; 26 } 27 else //若n是奇数,则砍掉(3*n+1)的一半 28 { 29 n = (3*n+1)/2; 30 flag[n] = false; 31 } 32 } 33 } 34 vector<int> result; 35 for (int j = 0; j < K; j++) 36 { 37 if(flag[a[j]] == true) 38 { 39 result.push_back(a[j]); 40 } 41 } 42 sort(result.begin(),result.end(),Cmp); //降序排序 43 for (int i = 0; i < result.size(); i++) 44 { 45 if(i == 0) 46 { 47 cout << result[i]; 48 } 49 else 50 { 51 cout << " " << result[i]; 52 } 53 } 54 return 0; 55 }
61. 素数对猜想 (20 分)
题目描述:
让我们定义dn为:dn=pn+1−pn,其中pi是第i个素数。显然有d1=1,且对于n>1有dn是偶数。“素数对猜想”认为“存在无穷多对相邻且差为2的素数”。
现给定任意正整数N
(<105),请计算不超过N
的满足猜想的素数对的个数。
输入格式:
输入在一行给出正整数N
。
输出格式:
在一行中输出不超过N
的满足猜想的素数对的个数。
输入样例:
20
输出样例:
4
解题思路:
哎呀呀呀,没时间了,马上考试了,解析见注释吧。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 bool isPrime(int n) //判断素数 5 { 6 if(n<=1) return false; 7 for(int i=2;i<=sqrt(n);i++) 8 { 9 if(n%i==0) 10 { 11 return false; 12 } 13 } 14 return true; 15 } 16 17 int main() 18 { 19 int N; 20 cin >> N; 21 int j = 0, count = 0; 22 int x = 2, y = 3; //题目所说的d1=1就是因为3-2=1 23 for (int i = 4; i <= N; i++) //从4开始找素数对 24 { 25 if(isPrime(i)) 26 { 27 x = y; 28 y = i; 29 if(y-x==2) //判断相邻的素数差是否为2 30 { 31 count++; 32 } 33 } 34 } 35 cout << count << endl; 36 return 0; 37 }
62. 住房空置率 (20 分)
题目描述:
在不打扰居民的前提下,统计住房空置率的一种方法是根据每户用电量的连续变化规律进行判断。判断方法如下:
-
在观察期内,若存在超过一半的日子用电量低于某给定的阈值 e,则该住房为“可能空置”;
-
若观察期超过某给定阈值 D 天,且满足上一个条件,则该住房为“空置”。
现给定某居民区的住户用电量数据,请你统计“可能空置”的比率和“空置”比率,即以上两种状态的住房占居民区住房总套数的百分比。
输入格式:
输入第一行给出正整数 N(≤1000),为居民区住房总套数;正实数 e,即低电量阈值;正整数 D,即观察期阈值。随后 N 行,每行按以下格式给出一套住房的用电量数据:
K E1 E2 ... EK
其中 K 为观察的天数,Ei 为第 i 天的用电量。
输出格式:
在一行中输出“可能空置”的比率和“空置”比率的百分比值,其间以一个空格分隔,保留小数点后 1 位。
输入样例:
5 0.5 10 6 0.3 0.4 0.5 0.2 0.8 0.6 10 0.0 0.1 0.2 0.3 0.0 0.8 0.6 0.7 0.0 0.5 5 0.4 0.3 0.5 0.1 0.7 11 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 11 2 2 2 1 1 0.1 1 0.1 0.1 0.1 0.1
输出样例:
40.0% 20.0%
解题思路:
这是一道水题,按照题目意思来就行了。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 int main() 4 { 5 int N,D; //N为居民区住房总套数,D为观察期阈值 6 double e; //e为低电量阈值 7 cin >> N >> e >> D; 8 int count1 = 0, count2 = 0; //count1为可能空置的天数,count2为空置的天数 9 for (int i = 0; i < N; i++) 10 { 11 int K; //K为观察的天数 12 cin >> K; 13 int count = 0; //用来记录用电量低于阈值的天数 14 double temp; 15 for (int j = 0; j < K; j++) 16 { 17 cin >> temp; 18 if(temp < e) 19 { 20 count++; 21 } 22 } 23 if(count > K/2) //若超过一半的日子用电量低于给定的阈值e,则该住房为“可能空置” 24 { 25 if(K > D) //若观察期超过某给定阈值D天,且满足上一个条件,则该住房为“空置” 26 { 27 count2++; 28 } 29 else 30 { 31 count1++; 32 } 33 } 34 } 35 printf("%.1f%% %.1f%%",count1*100.0/N,count2*100.0/N); //%%输出% 36 return 0; 37 }
63. 反转链表 (25 分)
题目描述:
给定一个常数 K 以及一个单链表 L,请编写程序将 L 中每 K 个结点反转。例如:给定 L 为 1→2→3→4→5→6,K 为 3,则输出应该为 3→2→1→6→5→4;如果 K 为 4,则输出应该为 4→3→2→1→5→6,即最后不到 K 个元素不反转。
输入格式:
每个输入包含 1 个测试用例。每个测试用例第 1 行给出第 1 个结点的地址、结点总个数正整数 N (≤105)、以及正整数 K (≤N),即要求反转的子链结点的个数。结点的地址是 5 位非负整数,NULL 地址用 −1 表示。
接下来有 N 行,每行格式为:
Address Data Next
其中 Address
是结点地址,Data
是该结点保存的整数数据,Next
是下一结点的地址。
输出格式:
对每个测试用例,顺序输出反转后的链表,其上每个结点占一行,格式与输入相同。
输入样例:
00100 6 4 00000 4 99999 00100 1 12309 68237 6 -1 33218 3 00000 99999 5 68237 12309 2 33218
输出样例:
00000 4 33218 33218 3 12309 12309 2 00100 00100 1 99999 99999 5 68237 68237 6 -1
解题思路:
这个题告诉了我一定一定要好好学习数据结构(流下了不学无术的泪水)。先定义一个MAXSIZE 100005,因为题目中最大地址是五位数99999。然后构造一个顺序表LinkNode用来存储数据data和下一地址next。需要注意的是一定要先读取完用来存放当前结点地址的临时变量temp,再用vector来存放每次输入的结点数据和下一结点的地址。计数器count用来记录能够首尾相连的结点数量,p指数当前结点,List用来存储可以连接上的顺序表。将所有能连接上的顺序表都放入List中,然后每K个结点就调用一个reverse来做反转,最后按格式输出就行了,最后一个结点的下一结点地址为-1。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define MAXSIZE 100005 //最大为五位数的地址 5 6 struct LinkNode //使用顺序表存储数据data和下一地址next 7 { 8 int data; 9 int next; 10 }; 11 12 int main() 13 { 14 vector<LinkNode> v(MAXSIZE); 15 int Head, N, K; 16 cin >> Head >> N >> K; //输入头地址 和 N,K 17 for (int i = 0; i < N; i++) 18 { 19 int temp; //用来存放结点地址的临时变量 20 cin >> temp; //这里不能和下一行写成一行,一定要先读取完temp 21 cin >> v[temp].data >> v[temp].next; 22 } 23 int count = 0; //count用来记录能够首尾相连的结点数 24 int p = Head; //p指示当前结点 25 int List[MAXSIZE]; //存储可以连接上的顺序表 26 while(p != -1) 27 { 28 List[count++] = p; 29 p = v[p].next; 30 } 31 for (int i = 0; i + K <= count; i += K) //每K个结点做一次反转 32 { 33 reverse(&List[i],&List[i+K]); 34 } 35 for (int i = 0; i < count-1; i++) 36 { 37 printf("%05d %d %05d ",List[i],v[List[i]].data,List[i+1]); 38 } 39 printf("%05d %d -1 ",List[count-1],v[List[count-1]].data); 40 return 0; 41 }
64. 开学寄语 (20 分)
题目描述:
下图是上海某校的新学期开学寄语:天将降大任于斯人也,必先删其微博,卸其 QQ,封其电脑,夺其手机,收其 ipad,断其 wifi,使其百无聊赖,然后,净面、理发、整衣,然后思过、读书、锻炼、明智、开悟、精进。而后必成大器也!
本题要求你写个程序帮助这所学校的老师检查所有学生的物品,以助其成大器。
输入格式:
输入第一行给出两个正整数 N(≤ 1000)和 M(≤ 6),分别是学生人数和需要被查缴的物品种类数。第二行给出 M 个需要被查缴的物品编号,其中编号为 4 位数字。随后 N 行,每行给出一位学生的姓名缩写(由 1-4 个大写英文字母组成)、个人物品数量 K(0 ≤ K ≤ 10)、以及 K 个物品的编号。
输出格式:
顺次检查每个学生携带的物品,如果有需要被查缴的物品存在,则按以下格式输出该生的信息和其需要被查缴的物品的信息(注意行末不得有多余空格):
姓名缩写: 物品编号1 物品编号2 ……
最后一行输出存在问题的学生的总人数和被查缴物品的总数。
输入样例:
4 2 2333 6666 CYLL 3 1234 2345 3456 U 4 9966 6666 8888 6666 GG 2 2333 7777 JJ 3 0012 6666 2333
输出样例:
U: 6666 6666 GG: 2333 JJ: 6666 2333 3 5
解题思路:
首先建立一个map用来记录需要被查缴的物品编号,map的key值一定要为string型(我之前写的int型,提交的时候有个测试用例WA了)。用俩个计数器来分别记录存在问题的学生人数和被查缴的物品总数,立一个flag用来判断单个学生有没有带违禁品(主要是为了判断要不要输入换行符)。若学生携带的物品出现在了map中,说明该学生携带了违禁品,输出该学生的姓名和被缴获的物品即可。最后输出俩个计数器记录的存在问题的学生人数和被查缴的物品总数。
AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() 5 { 6 int N,M; //N为学生人数,M为需要被查缴的物品种类数 7 cin >> N >> M; 8 map<string, int> m; //用来记录需要被查缴的物品编号 9 for (int i = 0; i < M; i++) 10 { 11 string temp; 12 cin >> temp; 13 m[temp] = 1; 14 } 15 int count_stu = 0; //存在问题的学生人数 16 int count_thing = 0; //被查缴的物品总数 17 for (int i = 0; i < N; i++) 18 { 19 string name; 20 int K; //个人物品数量 21 cin >> name >> K; 22 bool flag = false; //判断单个学生有没有带违禁品 23 for (int j = 0; j < K; j++) 24 { 25 string temp; 26 cin >> temp; 27 if(m[temp]==1) 28 { 29 if(!flag) 30 { 31 cout << name << ":"; 32 count_stu++; 33 flag = true; 34 } 35 count_thing++; 36 cout << " " << temp; 37 } 38 } 39 if(flag) 40 { 41 cout << endl; 42 } 43 } 44 cout << count_stu << " " << count_thing << endl; 45 return 0; 46 }