2026_CCF_CSP-J1_试卷完整解析
- 2026-09-20 12:42:24
2026 CCF CSP-J1 入门级 C++ 试卷完整解析
一、单项选择题(共15题,每题2分,共计30分,每题有且仅有一个正确选项。)
第1题 下列 C++ 数据类型中,能够精确存储 10^18 +1 这个整数的是( )
A. float B. long long C. double D. int
> 答案:B
> > 考点:数据类型精度与范围。float和double是浮点类型,无法精确表示大整数;int最大约2×10^9;long long最大约9.2×10^18,可以精确存储10^18+1。
第2题 十六进制数 2F5 转换为八进制数是( )
A. 1364 B. 1635 C. 1405 D. 1365
> 答案:D
> > 考点:进制转换。2F5(十六进制) = 757(十进制) = 1365(八进制)。先转十进制:2×256+15×16+5=757,再转八进制:757÷8=94余5,94÷8=11余6,11÷8=1余3,1÷8=0余1,从下往上读为1365。
第3题 执行下列 C++ 代码,输出是( )
int a = 7, b = 3;std::cout << a / b * b + a % b;
A. 9 B. 10 C. 7 D. 6
> 答案:C
> > 考点:整数除法与取模运算。a/b=7/3=2(整数除法截断),2*b=6,a%b=7%3=1,6+1=7。注意/和%优先级相同,从左到右计算。
第4题 初始时栈为空,将 1、2、3、4 依次入栈,入栈过程中允许随时出栈。下列出栈序列中不可能出现的是( )
A. 2,4,3,1 B. 1,2,3,4 C. 3,1,2,4 D. 1,4,3,2
> 答案:C
> > 考点:栈的出栈序列合法性。
选项C:要出3,需先入1、2、3,出3后栈中剩1、2(2在栈顶),下一个只能出2不能出1,所以"3,1"序列不可能。验证其他选项均可实现。
第5题 一棵有 100 个结点的完全二叉树,其中叶子结点个数是( )
A. 49 B. 50 C. 64 D. 51
> 答案:B
> > 考点:完全二叉树性质。设叶子数为n0,度为2的结点数为n2,则n0=n2+1。总结点数n=n0+n1+n2=2n2+1+n1。n=100时,2n2+n1=99,n1只能为1(完全二叉树最后一层只有一个左孩子的情况),n2=49,n0=50。
第6题 执行下列代码后 s 的值是( )
int s = 0;for (int i = 1; i <= 100; i++)if (i % 3 == 0 || i % 5 == 0)s += i;
A. 3048 B. 2733 C. 2318 D. 2418
> 答案:D
> > 考点:循环与条件求和(容斥原理)。
3的倍数之和=3×(1+2+...+33)=3×561=1683,5的倍数之和=5×(1+2+...+20)=5×210=1050,15的倍数之和=15×(1+2+...+6)=15×21=315。结果=1683+1050-315=2418。
第7题 上楼梯每步可上 1 级、2 级或 3 级,从地面(可视为第 0 级)走到第 8 级台阶共有多少种不同走法( )
A. 44 B. 121 C. 149 D. 81
> 答案:D
> > 考点:递推/动态规划。f(0)=1, f(1)=1, f(2)=2, f(n)=f(n-1)+f(n-2)+f(n-3)。f(3)=4, f(4)=7, f(5)=13, f(6)=24, f(7)=44, f(8)=81。
第8题 下图为 5×5 网格,行号、列号均从 0 开始,# 为障碍,. 为可通行格:
S . . # .. . . # .. . . # .# # . . E. . . # .
从 S 出发做广度优先搜索(BFS):初始时把 S 入队;每次取出队首格子,按"上、下、左、右"的顺序遍历它的四个相邻格子,越界、障碍或已访问的格子跳过,其余格子标记为已访问并入队。当 E 第一次入队时,已经入队过的格子(含 S 和 E)共有多少个( )
A. 15 B. 12 C. 14 D. 13
> 答案:D
> > 考点:BFS搜索过程模拟。按"上下左右"顺序逐层扩展,需要逐步模拟入队过程。S在(0,0),E在(3,4)。逐步模拟BFS扩展过程,直到E入队,共入队13个格子。
第9题 满足 1 ≤ n ≤ 100 且 gcd(n,60) = 6 的正整数 n 共有多少个( )
A. 8 B. 6 C. 4 D. 5
> 答案:B
> > 考点:数论(最大公约数)。gcd(n,60)=6意味着n是6的倍数且n/6与10互质。设n=6k,则gcd(6k,60)=6·gcd(k,10),需gcd(k,10)=1。k从1到16中与10互质的值:1,3,7,9,11,13,共6个。对应n=6,18,42,54,66,78,逐一验证gcd均为6。
第10题 某国硬币面值为 1 元、4 元、6 元且数量不限,凑出 9 元最少需要多少枚( )
A. 3 B. 4 C. 5 D. 2
> 答案:A
> > 考点:贪心/动态规划(硬币找零)。面值1,4,6凑9元。两枚组合:6+4=10≠9,6+1=7≠9,4+4=8≠9,不存在两枚解。三枚组合:4+4+1=9 ✓。最少需要3枚。
第11题 执行下列代码,输出是( )
int a[5] = {1, 3, 5, 7, 9};int *p = a + 2;*(p - 1) = p[0] + p[2];p[1] = *(a + 1) - a[0];cout << a[1] << "," << a[3];
A. 14,13 B. 8,13 C. 14,7 D. 14,2
> 答案:C
> > 考点:指针与数组运算。
第12题 在含 1000 个互不相同元素的升序数组中,用二分法查找给定值,最坏情况下需要与数组元素比较多少次?( )
A. 500 B. 9 C. 11 D. 10
> 答案:D
> > 考点:二分查找最坏比较次数。每次比较将范围缩小一半,最坏情况为⌊log2(1000)⌋+1。log2(1000)≈9.97,所以最坏需要比较10次(2^10=1024>1000≥2^9=512)。
第13题 数组 a[1..n] 的前缀和数组 s(即 s[i] = a[1]+a[2]+...+a[i])满足 s[i] = 3i² + i。则 a[10] 的值是( )
A. 252 B. 310 C. 58 D. 61
> 答案:C
> > 考点:前缀和差分。a[10]=s[10]-s[9]=(3×100+10)-(3×81+9)=310-252=58。
第14题 数轴上有 7 个点,坐标分别为 1、3、4、7、10、15、20。在数轴上选取一个整数坐标点 P,使 P 到这 7 个点的距离之和最小,这个最小距离和是( )
A. 37 B. 42 C. 40 D. 38
> 答案:A
> > 考点:中位数性质。距离和最小的点为中位数。7个点排序后中位数为第4个数=7。P=7时距离和=|7-1|+|7-3|+|7-4|+|7-7|+|7-10|+|7-15|+|7-20|=6+4+3+0+3+8+13=37。
第15题 一个无向图有 10 个顶点,其中 4 个顶点的度为 3,其余顶点的度均为 4,则该图的边数是( )
A. 36 B. 18 C. 17 D. 20
> 答案:B
> > 考点:图论握手定理。度之和=4×3+6×4=12+24=36。无向图中边数=度之和/2=36/2=18。
二、阅读程序(共40分)
程序输入不超过数组或字符串定义的范围;判断题正确填√,错误填×;除特殊说明外,判断题1.5分,选择题3分。
程序(1)
#include<iostream>using namespace std;intmain(){int n;cin >> n;int x = 1, y = 1;while (n > 0) {if (n % 2 == 0) {++x;} else {++x;++y;}n = n / 2;}cout << x << ' ' << y << endl;return 0;}
程序功能:读入非负整数 n,统计其二进制表示的总位数 x 和其中 1 的个数 y,输出 x 和 y。初始 x=1, y=1,每处理一位二进制位 x 加 1,若该位为 1 则 y 也加 1。
以下问题均假定输入的 n 为不超过 2³¹−1 的非负整数。
第16题(1分)当输入为 3 时,程序输出为 3 3。( )
> 答案:√ > > n=3,二进制11。初始x=1,y=1。第1轮:3%2=1(奇),x=2,y=2,n=1。第2轮:1%2=1(奇),x=3,y=3,n=0。输出"3 3"正确。
第17题 将第 11 行的 ++x; 删除后,程序输出的两个数一定相等。( )
> 答案:× > > 删除else分支中的++x后,x只在偶数位时递增,y只在奇数位时递增。x=1+0的个数,y=1+1的个数。两者不一定相等。例如n=4(二进制100):2个零位、1个一位,x=3,y=2,不相等。
第18题 假设输入为非负整数,则程序输出的第一个数一定不小于第二个数。( )
> 答案:√ > > x统计总二进制位数(含初始1),y统计1的个数(含初始1)。总位数≥1的个数恒成立,所以x≥y。
第19题 将第 7 行的 while (n > 0) 改为 while (n >= 0) 后,程序可能出现的问题是( )。
A. 陷入死循环 B. 输出结果比原来大 C. 输出结果比原来小 D. 输出结果不受影响
> 答案:A > > 当n=0时,0>=0为true进入循环,0%2=0走偶数分支++x,n=0/2=0,仍然>=0,永远无法退出→死循环。对于n>0最终也会到n=0后死循环。
第20题 当输入为 6 时,输出为( )。
A. 3 3 B. 4 2 C. 4 3 D. 5 2
> 答案:C > > n=6,二进制110。初始x=1,y=1。第1轮:6%2=0偶,x=2,n=3。第2轮:3%2=1奇,x=3,y=2,n=1。第3轮:1%2=1奇,x=4,y=3,n=0。输出"4 3"。
第21题 若输入 n 依次取遍 0,1,2,...,2³¹−1 中的所有整数,则程序输出的第二个数恰好为 2 的次数为( )。
A. 16 B. 30 C. 31 D. 32
> 答案:C > > y=2意味着二进制中恰好1个1(初始y=1,遇到1个1位后y=2)。即n是2的幂。n从0到2³¹−1,2的幂有2⁰,2¹,...,2³⁰共31个(n=0时y=1不计入)。
程序(2)
#include<iostream>#include<sring>#include<algorithm>using namespace std;int a[100007], b[100007], c[100007], carry[100007];string input_str;int a_len, b_len;intmain(){cin >> input_str;a_len = input_str.size();for (int i = 0; i < a_len; i++) {a[i] = input_str[a_len - i - 1] - '0';}cin >> input_str;b_len = input_str.size();for (int i = 0; i < b_len; i++) {b[i] = input_str[b_len - i - 1] - '0';}carry[0] = 0;for (int i = 0; i < max(a_len, b_len) + 1; i++) {c[i] = a[i] + b[i] + carry[i];if (c[i] >= 10) {carry[i + 1] = 1;c[i] -= 10;} else {carry[i + 1] = 0;}}for (int i = max(a_len, b_len); i >= 0; i--) {cout << c[i];}cout << endl;return 0;}
程序功能:高精度加法。将两个大整数以字符串读入,逆序存储为整型数组,逐位相加并处理进位,最后从高位到低位输出结果。输出范围固定为 max(a_len, b_len)+1 位(可能含前导零)。
本题输入的两个数均为非负整数,位数不超过100000,可能包含前导零。
第22题 当输入为 123 456 时,程序输出为 0579。( )
> 答案:√ > > 123+456=579。程序固定输出max(3,3)+1=4位。123逆序为3,2,1;456逆序为6,5,4。逐位相加:c[0]=3+6=9, c[1]=2+5=7, c[2]=1+4=5, c[3]=0+0+0=0。输出"0579",正确。
第23题 假设输入的两个数均不含前导零,则程序输出的结果也一定不会含有前导零。( )
> 答案:× > > 程序固定输出max(a_len,b_len)+1位。当和的位数恰好等于max(a_len,b_len)时(如123+456=579,3位数),输出4位含前导零"0579"。
第24题 将第 21 行改为 c[i]=a[i]+b[i]; 后,程序输出的结果一定比原来的结果小。( )
> 答案:× > > 去掉进位后,每位独立相加。当无进位时(如输入"1 2",c[0]=3),结果与原程序相同。只有发生进位时结果才不同,因此不是"一定更小"。
第25题 当输入为 12345 678 时,输出为( )。
A. 012923 B. 013023 C. 13023 D. 130230
> 答案:B > > 12345+678=13023。max(5,3)+1=6位输出。a逆序:5,4,3,2,1;b逆序:8,7,6,0,0。c[0]=5+8=13→3进1,c[1]=4+7+1=12→2进1,c[2]=3+6+1=10→0进1,c[3]=2+0+1=3,c[4]=1+0=1,c[5]=0+0=0。输出"013023"。
第26题 将第 22 行的 if (c[i]>=10) 改为 if (c[i]>10) 后,当输入为 95 15 时,输出为( )。
A. 01010 B. 110 C. 140 D. 1410
> 答案:A > > 修改后c[i]=10时不进位。a逆序:5,9;b逆序:5,1。c[0]=5+5=10,10>10为false,不进位,c[0]=10。c[1]=9+1=10,不进位,c[1]=10。c[2]=0+0+0=0。输出从i=2到0:0,10,10,即"01010"。
第27题 假设输入的两个数均为 n 位正整数(不含前导零),且它们的和小于 10ⁿ,则程序输出的字符串一定满足( )。
A. 第一个字符一定不为 '0'
B. 长度一定为 n
C. 长度一定为 n+1,且第一个字符为 '0'
D. 长度可能为 n+2
> 答案:C > > 两个n位数之和<10ⁿ说明没有进位到第n+1位(carry[n]=0)。程序固定输出max(n,n)+1=n+1位。第n位(最高位)c[n]=a[n]+b[n]+carry[n]=0+0+0=0。所以输出长度n+1且首位为'0'。
程序(3)
#include<iostream>using namespace std;boolcheck_prime(int x){if (x <= 1) return false;for (int i = 2; i * i <= x; i++) {if (x % i == 0) return false;}return true;}int n;voidsearch_result(int x){if (!check_prime(x)) return;if (x >= n) {cout << x << endl;return;}for (int i = 0; i <= 9; i++) {search_result(x * 10 + i);}}intmain(){cin >> n;for (int i = 1; i <= 9; i++) search_result(i);return 0;}
程序功能:输出所有不小于 n 的"前缀质数"(即该数本身及其每一位前缀均为质数的数)。从 1-9 开始递归搜索,每个前缀必须是质数才能继续扩展,达到 ≥n 则输出。
第28题 当输入为 10 时,程序的输出共有 10 行。( )
> 答案:× > > n=10时,输出所有≥10的前缀质数。从2开始DFS搜索:23,233,239,29,293,...从3开始:31,311,313,317,37,373,379,...从5开始:53,59,...从7开始:71,73,79,...输出行数远超10行。
第29题 若输入的 n 不大于 5,则程序的输出中一定包含 5。( )
> 答案:√ > > n≤5时,从i=5开始search_result(5),5是质数且5≥n,直接输出5。所以5一定被输出。
第30题 若输入的 n 大于 10,将第 17 行的 for (int i=0;i<=9;i++) 改为 for (int i=1;i<=9;i+=2) 后,程序的输出结果一定不变。( )
> 答案:√ > > 修改后只搜索奇数位(1,3,5,7,9),跳过偶数位0,2,4,6,8。偶数>2都不是质数,check_prime会返回false跳过。因此修改后不会遗漏任何输出,结果不变。
第31题 当输入为 24 时,程序输出的第 3 行为( )。
A. 23 B. 29 C. 31 D. 239
> 答案:B > > n=24,DFS顺序输出≥24的前缀质数。从2开始:23<24继续扩展→239(≥24)输出第1行,233(≥24)输出第2行;然后29(≥24)输出第3行。从3开始:31(≥24)输出第4行...第3行为29。
第32题 下列关于该程序输出的说法中,正确的是( )。
A. 输出的数一定按照从小到大的顺序排列
B. 随着输入 n 的增大,输出的行数一定不会增加
C. 输出的数的个位数字只可能是 3 或 7
D. 输出的每个大于等于 10 的数,十进制下删去它的末位数字后得到的数一定是质数
> 答案:D > > A错误:DFS顺序不保证升序(如239出现在29之前)。B正确但非最佳描述:n增大时≥n的数减少,行数确实不增。C错误:输出含末位1,9的数(如31,59,79)。D正确:程序要求每个前缀都是质数才能递归,删去末位后得到的前缀必然通过了check_prime检查,一定是质数。D描述了程序的核心性质,最为准确。
第33题 当输入为 200 时,程序输出的行数为( )。
A. 12 B. 13 C. 14 D. 15
> 答案:C > > 需统计所有≥200的前缀质数。从2,3,5,7开始DFS搜索,逐个验证前缀均为质数且本身≥200的数。枚举:211,223,227,229,233,239,251(25非质跳过)...共14个。
三、完善程序(单选题,每小题3分,共计30分)
程序(1)进制减半
给定 n、m,再给定一个 m×n 进制下的数 A,其各个数位上的数按照从高位到低位的顺序给出,请你将其转化为 n 进制,并同样按照从高位到低位的顺序输出。
输入的第一行依次为 n、m 和 A 的位数 d,接下来 d 个数 a_d, a_{d-1}, ..., a_1 从高位到低位描述各个数位上的数。
数据满足 2 ≤ n,m ≤ 10,1 ≤ d ≤ 18,0 ≤ A < 2⁶³,对于所有 1 ≤ i ≤ d,0 ≤ a_i < m×n。
以下程序按"逐位除以 n"的方法完成进制转换。请补全程序。
#include<iostream>constexpr int N = 100005;long long b[N];intmain(){long long n, m, d;std::cin >> n >> m >> d;int len = 1;for (int i = 0; i < d; i++) {long long x;std::cin >> x;for (int j = len; j >= 1; j--)b[j] = ①;b[0] = ②;len++;for (int j = 0; j < len; j++)if (b[j] >= n) {b[j + 1] += ③;b[j] = ④;if (j + 1 == len) len++;}}while (⑤) len--;for (int i = len - 1; i >= 0; i--)std::cout << b[i] << ' ';return 0;}
算法说明:将 m×n 进制数转为 n 进制。每读入一个高位数字 x,先将现有结果左移一位(乘以进制基数),再加上新位,然后处理进位(超过 n 的位向高位进位),最后去除前导零。
第34题 ①处应填( )
A. b[j] * n B. b[j] * m C. b[j - 1]* n D. b[j - 1] *m
> 答案:B > > 考点:进制转换——高位左移。每读入一个新位,现有结果需乘以进制基数。m×n进制转n进制分两步:先将每位乘以m(b[j]=b[j-1]*m),再加上新数字x到b[0],然后处理进位(≥n的位除以n进位)。循环j从len到1,b[j]=b[j-1]*m实现每位乘m。
第35题 ②处应填( )
A. x * n B. x C. 0 D. m
> 答案:B > > ②处b[0]=x,即把新读入的数字放到最低位。前面①已将所有位乘以m左移,这里加上新数字x。
第36题 ③处应填( )
A. b[j] / m B. b[j] % n C. b[j] % m D. b[j] / n
> 答案:D > > ③处是进位操作:当b[j]≥n时,向高位b[j+1]加上b[j]/n(除以n的商作为进位)。
第37题 ④处应填( )
A. b[j] / m B. b[j] % n C. b[j] % m D. b[j] / n
> 答案:B > > ④处是进位后当前位保留:b[j] = b[j] % n(除以n的余数保留在当前位)。
第38题 ⑤处应填( )
A. len > 0 && b[len - 1] == 0
B. len > 0 && b[0] == 0
C. len > 1 && b[len - 1] == 0
D. len > 1 && b[0] == 0
> 答案:C > > ⑤处去除前导零:从最高位开始,如果最高位为0则缩短len。条件len>1确保至少保留1位(避免全0时len变为0),且b[len-1]==0检查最高位是否为0。
程序(2)平衡分割
给定一个长度为 n 的字符串,其中每个字符都是一个十六进制数位。例如,字符串 016A 表示十进制下的四个数 0、1、6、10。
现在请选择 k 个(k 是你选定的数)切分位置 p_1, p_2, ..., p_k,其中 1 ≤ k < n,且 1 ≤ p_1 < p_2 < ... < p_k < n。再令 p_0 = 0,p_{k+1} = n。
对于每个 0 ≤ i ≤ k,计算第 p_i+1 个数到第 p_{i+1} 个数的平均值,记作 b_i。你的目标是使 b_0, b_1, ..., b_k 中最大值与最小值之差尽可能小,并输出这个最小值。
其中 2 ≤ n ≤ 20。输入字符串中的字符只可能是 0~9 或 A~F。本题假定字符采用 ASCII 编码。输出答案时保留小数点后 6 位。
以下程序通过递归枚举所有可能的连续分段方案。请补全程序。
#include<iostream>#include<algorithm>#include<iomanip>using namespace std;constexpr int N = 25;int n, a[N];char s[N];double ans = 1e100;intvalue(char c){ return ①; }voidsplit(int l, int cnt, double mnb, double mxb){if (l > n) {if (cnt == 0) return;ans = min(ans, mxb - mnb);return;}int sum = 0;for (②) {sum += a[r];double nwb = ③;split(④);}}intmain(){cin >> n >> s + 1;for (int i = 1; i <= n; ++i)a[i] = value(s[i]);split(⑤);cout << fixed << setprecision(6) << ans;return 0;}
算法说明:递归枚举所有分段方案。split(l, cnt, mnb, mxb) 表示当前处理到第 l 个字符,已分了 cnt 段,目前所有段平均值的最小值为 mnb、最大值为 mxb。枚举当前段从位置 l 到 r,计算该段平均值,更新 min/max 并递归处理剩余部分。
第39题 ①处应填( )
A. c <= '9' ? c - '0' : c - 'A' + 10
B. c <= '9' ? c - '0' : c - 'A'
C. c <= '9' ? c - '0' + 1 : c - 'A' + 10
D. c <= '9' ? c - '0' : c - 'A' + 9
> 答案:A > > 考点:十六进制字符转数值。'0'-'9'对应0-9,'A'-'F'对应10-15。c <= '9' 时 c - '0' 得 0-9,否则 c - 'A' + 10 得 10-15。
第40题 ②处应填( )
A. int r = 1; r <= n; r++
B. int r = 1; r < n; r++
C. int r = 1; r <= n; r+=2
D. int r = 1+1; r <= n;++r
> 答案:A > > 考点:枚举右端点。当前段从位置 l 开始,r 从 l 枚举到 n(含 n),表示当前段为 [l, r]。
第41题 ③处应填( )
A. sum/(r-l+1)
B. 1.0*sum/(r-l+1)
C. 1.0*sum/(r-l)
D. sum*1.0/n
> 答案:B
第42题 ④处应填( )
A. r+1, cnt+1, min(mnb,nwb), max(mxb,nwb)
B. r+1, cnt+1, minb, maxb
C. r+1, cnt, mwb, mb
D. r+1, cnt, min(mnb,nwb), max(mxb,nwb)
> 答案:A
第43题 ⑤处应填( )
A.0,0,1e100,-1e100
B.0,0,-1e100,1e100
C. 1,0,-1e100,1e100
D. 1,0,1e100,-1e100
> 答案:D
试卷总结
部分 | 题量 | 分值 | 核心考点 |
单项选择题 | 15题 | 30分 | 数据类型、进制转换、栈、二叉树、BFS、数论、指针、二分查找、前缀和、图论 |
阅读程序(1) | 6题 | 11.5分 | 二进制位统计、循环边界、组合计数 |
阅读程序(2) | 6题 | 10.5分 | 高精度加法、进位处理、前导零分析 |
阅读程序(3) | 6题 | 10.5分 | 质数判断、DFS递归、前缀质数性质 |
完善程序(1) | 5题 | 15分 | 进制转换、数组模拟、进位处理 |
完善程序(2) | 5题 | 15分 | 递归枚举分段、十六进制转换、区间求平均 |
难度评价:标准入门级,与往年CSP-J1持平。重点考查基础算法理解与代码追踪能力,完善程序部分考查进制转换和递归分段的经典算法实现。