2020 CCF认证第一轮(CSP-J)真题
二、阅读程序题
(程序输入不超过数组或字符串定义的范围,判断题正确填√错误填X;除特殊说明外,判断题 1.5分,选择题3分,共计4 分)
第一题
01 #include <cstdlib>
02 #include <iostream>
03 using namespace std;
04
05 char encoder[26]= {'C','S','P',0};
06 char decoder[26];
07
08 string st;
09
10 int main(){
11 int k=0;
12 for (int i=0;i<26;++i)
13 if (encoder[i] != 0) ++k;
14 for (char x='A';x<='Z;++x){
15 bool flag = true;
16 for (int i=0;i<26; ++i)
17 if (encoder[i] == x){
18 flag = false;
19 break;
20 }
21 if (flag){
22 encoder[k] = x;
23 ++k;
24 }
25 }
26 for (int i=0;i<26;++i)
27 decoder[encoder[i]-'A']=i+'A';
28 cin >> st;
29 for (int i=0;i<st.length();++i)
30 st[i] = decoder[st[i] -'A'];
31 cout << st;
32 return 0;
33}
程序分析
主要考查小朋友们读写程序能力和逻辑思维能力,此程序实现的一个加密解密的功能;它使用一个26个元素的数组 encoder 和一个26个元素的数组 decoder,分别用于加密和解密。
程序首先初始化 encoder 数组为 {'C','S','P',0},然后通过遍历数组找到不为零的元素个数,并输出这些元素。接着,程序遍历从 A 到 Z 的所有字母,检查它们是否已经在 encoder 数组中出现过。如果未出现过,则将该字母添加到 encoder 数组中。程序也会相应地更新 decoder 数组,以便进行解密。
然后,程序从用户获取一个字符串,并将该字符串中的每个字符用相应的解码方式进行解密。最后,程序输出解密后的字符串。
总之,这段程序实现了一个简单的加密和解密功能,其中加密方式是将大写的C、S、P三个字母替换为 大写的A、B、C三个字母,具体加密前字母和加密后字母如下:
加密前:ABCDEFGHIJKLMNOPQRSTUVWXYZ
加密后:DEAFGHIJKLMNOPQCRSBTUVWXYZ
判断题
1)、输入的字符串应当只由大写字母组成,否则在访问数组时可能越界
2)、若输入的字符串不是空串,则输入的字符串与输出的字符串一定不一样
3)、将第 12行的“i<26”改为“i<16”,程序运行结果不会改变
4)、将第 26行的"i<26”改为“i<16”,程序运行结果不会改变
答案:1√ 2 × 3 √ 4 ×
答案分析:
1、从程序分析可以得出输入的只能是26个大写字母
2、输入的是S后面的字母输出的就是一样的
3、第12行的作用是读取encoder数组里面的个数,程序中只给出CSP三个,所以改成16不影响,改成6都可以,只要超过encoder数组的个数就行
4、第26是对26个字母进行解码,如果改成16了,会发现后面的一部分就会出错
单选题
5)、出的字符串为“ABCABCABCA”,则下列说法正确的是
A、输入的字符串中既有 S 又有 P
B、输入的字符串中既有 S 又有 B
C、输入的字符串中既有 A 又有 P
D、输入的字符串中既有 A 又有 B
答案:A
答案分析:因为输出的结果中有B和C,所以输入的字符串就是S和P,所以答案A
6)、若输出的字符串为“CSPCSPCSPCSP”,则下列说法正确的是
A、输入的字符串中既有 P 又有 K
B、输入的字符串中既有 J 又有 R
C、输入的字符中中既有 J 又有 K
D、输入的字符串中既有 P又有 R
答案:D
答案分析:因为输出的结果中有C和S,所以输入的字符串就是P和R,所以答案D
第二题
1 #include<iostream>
2 using namespace std;
3
4 long long n, ans;
5 int k, len;
6 long long d[1000000];
7
8 int main(){
9 cin >> n >> k;
10 d[0] = 0;
11 len= 1;
12 ans = 0;
13 for (long long i = 0; i<n; ++i) {
14 ++d[0];
15 for (int j = 0;j + 1<len; ++j){
16 if (d[j] == k){
17 d[j] = 0;
18 d[j + 1] += 1;
19 ++ans;
20 }
21 }
22 if (d[len- 1] == k){
23 d[len - 1] = 0;
24 d[len] =1;
25 ++len;
26 ++ans;
27 }
28 }
29 cout << ans << endl;
30 return 0;
31 }
程序分析
主要考查小朋友们读写程序能力和逻辑思维能力,此程序小朋友们不认真理解还是比较容易出错的,甚至有可能看不懂题目;此程序其实要实现的功能是将十进制数n,转换成对应的k进制数,输出的结果是在转换的过程中总的进位的次数,也就是ans;其中的len表示的是长度;当k为1时,n为1,1进制的1,len 为2,所以错误;输入n为1且 k > 1 时,ans == n;n转化为 len 位的 k 进制数字值 最大值为 k^len - 1 ,因此k^len>n。
判断题
1)、若k=1,则输出ans 时,len=n。
2)、若 k>1,则输出ans 时,len 一定小于n。
3)、若 k>1,则输出ans 时,一定大于n。
答案:1× 2 ×3 √
单选题
4)、 若输入的n等于,输入的k 为1,则输出等于
A、1
B、
C、
D、
答案:D
5)、若输入的n等于205,891,132,094,649(即),输入的k为3,则输出等于
A、
B、
C、
D、
答案:B
6)、若输入的n 等于 180,01,02,000,098,输入的k为10,则输出等于
A、11,112,222,444,543
B、11,122,222,444,453
C、11,122,222,444,543
D、11,112,222,444,453
答案:B
考点分析:4、当输入的 k 为 1 时,表示的是1进制,所以每一次都会进,len为2,但是后面触发不了len++的条件,结果就是,len一直是2,每次 d[0]++ 都会进位,输出 ans == n。
5、第1位,每k次运算进位1次;
第2位,每次运算进位1次;
……
因此第1位,会产生330/3次进位,第2位会产生330/次进位……最后一位,会产生1次进位。
因此答案 = / 3 + / + … + 1
根据等比数列求和公式Sn = (– 1) / (3 - 1)
6、根据上面的分析,可以得到答案为B
第三题
#include <algorithm>
#include <iostream>
using namespace std;
int n;
int d[50][2];
int ans;
void dfs(int n,int sum) {
if (n == 1) {
ans = max(sum, ans);
return;
}
for (int i=1;i<n;++i){
int a= d[i -1][0],b = d[i - 1][1];
int x=d[i][0],y = d[i][1];
d[i-1][0]=a+x;
d[i- 1][1]=b+y;
for (int j=i;j<n-1;++j)
d[j][0] = d[j + 1][0],d[j][1] = d[j + 1][1];
int s=a+x+abs(b- y);
dfs(n-1,sum +s);
for (int j=n-1;j>i;--j)
d[j][0] = d[j - 1][0],d[j][1]= d[j-1][1];
d[i- 1][0]=a,d[i- 1][1]=b;
d[i][0] =x,d[i][1] = y;
}
}
int main() {
cin >>n;
for (int i=0;i<n;++i)
cin >>d[i][0];
for (int i=0;i<n;++i)
cin >> d[i][1];
ans = 0;
dfs(n,0);
cout << ans << endl;
return 0;
}
程序分析
主要考查小朋友们读写程序能力和逻辑思维能力,程序通过递归实现深度优先搜索(DFS)来寻找满足条件的子数组。在递归过程中,维护一个当前已选取的元素的和sum,每次扩展当前子数组时,将当前位置的元素加到前面已经选取的元素的和上,然后将这个和加上当前位置与下一个位置的差的绝对值,作为新的sum值。递归完成后,更新答案ans为当前和sum与ans的最大值。
假设输入的 n 是不超过 5 的正整数,d[i][0]d[i][1]都是不超过10000的正整数,完成下面的判断题和单选题:
判斯题
1) 输入 n 为0,此程序可能会死循环或发生运行错误
2) 若输入n为20,接下来的输入全为0,则输出为 0
3) 输出的数一定不小于输入的 d[i][0]和 d[i][1]的任意一个
答案:1× 2√ 3 ×
答案分析:输入0,啥也不做,直接输出0;输入20个0,求和依然是0,ans也是0;输入的值也有可能小于输入的值,比如输入n=2,0 0 和 3 3,这时输出的是0
单选题
4) 若输入的n为20,接下来的输入是 20个9和20个0,则输出为
A.1890 B.1881 C.1908 D.1917
答案:B
5) 若输入的n为3,接下来的输入是 3 个0和3 个5,则输出为
A.2000 B. 2010 C.2030 D.2020
答案:C
6) 若输入的n 为 15,接下来的输入是15到1,以及15 到1,则输出为
A. 2440 B. 2220 C.2240 D. 2420
答案:C
考点分析:
4、第二列为0,加0等于没加不用管,可以忽略
第1次合并:9+9=9*2
第2次合并:18+9=9*3
第3次合并:27+9=9*4
…
第19次得到:9*20
因此和 = 9*2 + 9*3 + … + 9 * 20 = 1881
5、第1次合并:5-5=0
第2次合并:5+5-5=5=5*1
第3次合并:10+5-5=10=5*2
…
第29次合并:5*30-5=5*28
求和 = 5 * (1 + 2 + … + 28) = 2030
6、对于第1列:
第1次合并 = 15+14
第2次合并 = 15+14+13
…
第14次合并 = 15+14+13+12+…+1
15*14+14*14+13*13+…+1*1 = 1225
对于第2列:
第1次合并 = 15-14
第2次合并 = 15+14-13
第3次合并 = 15+14+13-12
……
第14次合并 = 15+14+13+12+…+2-1
15*13+14*12+…+3*1=1001,最后加上14个1:1015
最终答案是:2240