【题目原文引自 CCF 2026 CSP-J1 真题卷,解析为本站原创整理】 全文 43 题的题干、选项均已对照真题卷原文核验;答案与分步解析为个人整理结果,最终以 CCF 官方公布为准。
真题卷完整扫描页见本站《2026 CSP-J 第一轮认证真题卷》。https://noi.hnai.net/csp/460.html
一、参考答案速查表
| 题号 | 答案 | 题号 | 答案 | 题号 | 答案 |
|---|---|---|---|---|---|
| 1 | B | 12 | D | 23 | × |
| 2 | D | 13 | C | 24 | × |
| 3 | C | 14 | A | 25 | B |
| 4 | C | 15 | B | 26 | A |
| 5 | B | 16 | √ | 27 | C |
| 6 | D | 17 | × | 28 | × |
| 7 | D | 18 | √ | 29 | √ |
| 8 | C | 19 | A | 30 | √ |
| 9 | B | 20 | C | 31 | B |
| 10 | A | 21 | C | 32 | D |
| 11 | A | 22 | √ | 33 | C |
| 34 | D | 35 | B | 36 | D |
| 37 | B | 38 | C | 39 | A |
| 40 | A | 41 | A | 42 | B |
| 43 | A |
分段小结:
单选 B D C C B D D C B A A D C A B;
阅读程序(1) √ × √ A C C;(2) √ × × B A C;(3) × √ √ B D C;
完善程序(1) D B D B C;(2) A A A B A。
二、单项选择题(共 15 题,每题 2 分,共计 30 分)
第 1 题
下列 C++ 数据类型中,能够精确存储 10¹⁸ + 1 这个整数的是( )
A. float B. long long C. double D. int
参考答案:B
分步解析:10¹⁸ + 1 = 1000000000000000001,是一个 19 位十进制整数。
int:32 位,上限 2147483647(10 位),装不下;float:32 位单精度,有效数字仅约 7 位;double:64 位双精度,有效数字约 15~16 位,存 19 位数会丢精度;long long:64 位有符号整数,上限约 9.22×10¹⁸,10¹⁸ + 1 可精确存储。
考点:C++ 数据类型范围与精度。
第 2 题
十六进制数 2F5 转换为八进制数是( )
A. 1364 B. 1635 C. 1405 D. 1365
参考答案:D
分步解析:
- 十六进制转十进制:2F5₁₆ = 2×256 + 15×16 + 5 = 512 + 240 + 5 = 757;
- 十进制转八进制(除 8 取余):757÷8=94 余 5,94÷8=11 余 6,11÷8=1 余 3,1÷8=0 余 1;
- 逆序排列得 1365₈(验算:1×512+3×64+6×8+5 = 757 ✓)。
考点:进制转换。
第 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 → a / b * b = 2 * 3 = 6;a % b = 1;6 + 1 = 7。选 A 的同学是把 a/b*b 当成了 a(还原成 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
分步解析:
- A:1入、2入、2出;3入、4入、4出、3出、1出 → 合法;
- B:每次「入一个出一个」→ 合法;
- C:第一个出 3,说明 1、2、3 已在栈中,此时栈顶是 2,下一个却要出 1 → 非法;
- D:1入1出;2、3、4 依次入,再 4、3、2 依次出 → 合法。
考点:栈的入栈/出栈序列合法性。
第 5 题
一棵有 100 个结点的完全二叉树,其中叶子结点个数是( )
A. 49 B. 50 C. 64 D. 51
参考答案:B
分步解析:编号从 1 起,最后一个非叶子结点是 ⌊100/2⌋ = 50 号;叶子结点为 51~100 号,共 100 − 50 = 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+6+…+99 = 1683)+ 5 的倍数和(5+10+…+100 = 1050)− 15 的倍数和(15+30+…+90 = 315)= 1683 + 1050 − 315 = 2418。
考点:容斥原理、循环累加。
第 7 题
上楼梯每步可上 1 级、2 级或 3 级,从地面(可视为第 0 级)走到第 8 级台阶共有多少种不同走法( )
A. 44 B. 121 C. 149 D. 81
参考答案:D
分步解析:设 f(i) 为走到第 i 级的走法数,则 f(i) = f(i−1) + f(i−2) + f(i−3),f(0)=1,f(1)=1,f(2)=2 → 4、7、13、24、44、81。注意选项 A 的 44 是第 7 级,属于「少递推一步」的陷阱。
考点:递推(三阶斐波那契类)。
第 8 题
下图为 5×5 网格,行号、列号均从 0 开始,# 为障碍,. 为可通行格:
S . . # .
. . . # .
. . . # .
# # . . E
. . . # .
从 S 出发做广度优先搜索(BFS):初始时把 S 入队;每次取出队首格子,按「上、下、左、右」的顺序遍历四个相邻格子,越界、障碍或已访问的跳过,其余标记为已访问并入队。当 E 第一次入队时,已经入队过的格子(含 S 和 E)共有多少个( )
A. 15 B. 12 C. 14 D. 13
参考答案:C
分步解析:按队列顺序逐个登记(序号即入队次序):
- (0,0)=S 2. (1,0) 3. (0,1) 4. (2,0) 5. (1,1) 6. (0,2)
- (2,1) 8. (1,2) 9. (2,2) 10. (3,2) 11. (4,2) 12. (3,3) 13. (4,1) 14. (3,4)=E
关键在 2~3 行中间那一列 # 把路卡住,只能从 (2,2) 向下钻到 (3,2) 再展开。建议一格一格写队列,凭感觉数极易数成 13 或 15。
考点:BFS 的队列模拟。
第 9 题
满足 1 ≤ n ≤ 100 且 gcd(n, 60) = 6 的正整数 n 共有多少个( )
A. 8 B. 6 C. 4 D. 5
参考答案:B
分步解析:设 n = 6t,则 gcd(n, 60) = 6·gcd(t, 10),要等于 6 就必须 gcd(t, 10) = 1(t 既不是 2 的倍数也不是 5 的倍数)。又 n ≤ 100 → t ≤ 16。
t ∈ {1, 3, 7, 9, 11, 13} → n ∈ {6, 18, 42, 54, 66, 78},共 6 个。
网上有解析只算出 4 个,是把条件误当成 gcd(t, 60) = 1,漏掉了 t = 3、t = 9。
考点:最大公约数、互质计数。
第 10 题
某国硬币面值为 1 元、4 元、6 元且数量不限,凑出 9 元最少需要多少枚( )
A. 3 B. 4 C. 5 D. 2
参考答案:A
分步解析:枚举可行组合——6+1+1+1 = 4 枚;4+4+1 = 3 枚;4+1×5 = 6 枚;1×9 = 9 枚。最少 3 枚。注意这不是简单的贪心题,凑不出 9−6=3 所以不能先取 6。
考点:枚举/完全背包思想。
第 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
参考答案:A
分步解析:p = a + 2 指向 a[2]=5。
*(p−1) = p[0] + p[2]→ a[1] = a[2] + a[4] = 5 + 9 = 14(a[1] 被改写);p[1] = *(a+1) − a[0]→ a[3] = a[1] − a[0] = 14 − 1 = 13(注意此时 a[1] 已是 14,不是 3);- 输出
14,13。
考点:指针运算、指针与数组的关系。
第 12 题
在含 1000 个互不相同元素的升序数组中,用二分法查找给定值,最坏情况下需要与数组元素比较多少次?( )
A. 500 B. 9 C. 11 D. 10
参考答案:D
分步解析:二分查找最坏比较次数 = ⌈log₂(n+1)⌉ = ⌈log₂1001⌉;2⁹ = 512 < 1001 ≤ 1024 = 2¹⁰ → 10 次。
考点:二分查找的时间复杂度。
第 13 题
数组 a[1..n] 的前缀和数组 s(即 s[i] = a[1] + … + a[i])满足 s[i] = 3i² + i。则 a[10] 的值是( )
A. 252 B. 310 C. 58 D. 61
参考答案:C
分步解析:由差分 a[i] = s[i] − s[i−1] → a[10] = s[10] − s[9] = (3×100 + 10) − (3×81 + 9) = 310 − 252 = 58。选项 A(252)就是 s[9]、选项 B(310)就是 s[10],都是给忘了差分这一步的同学准备的。
考点:前缀和与差分。
第 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 计算: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 = 18。选项 A 就是「忘记除以 2」的结果。
考点:握手定理。
三、阅读程序(共 40 分)
程序(1):进制减半模拟
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int x = 1, y = 1;
while (n > 0) {
if (n % 2 == 0) {
++x;
} else {
++x; // 第 11 行
++y;
}
n = n / 2;
}
cout << x << ' ' << y << endl;
return 0;
}
程序功能:循环把 n 除以 2。x = 循环次数 + 1 = 二进制位数 + 1;y = 遇到的奇数次数 + 1 = 二进制中 1 的个数 + 1。看懂这两个计数器的含义,本组 6 题就都通了。
16.(1 分)当输入为 3 时,程序输出为 3 3。( )→ √
3 = 11₂:n=3 奇 → x=2, y=2, n=1;n=1 奇 → x=3, y=3, n=0 → 输出 3 3。
17. 将第 11 行的 ++x; 删除后,程序输出的两个数一定相等。( )→ ×
删掉后偶数只加 x、奇数只加 y,两者不再同步。取 n = 1:只走奇数分支 → x = 1、y = 2,输出 1 2 不相等。
18. 假设输入为非负整数,则程序输出的第一个数一定不小于第二个数。( )→ √
x 统计总位数 + 1,y 统计 1 的个数 + 1,1 的个数不可能超过总位数,故 x ≥ y 恒成立。
19. 将第 7 行 while (n > 0) 改为 while (n >= 0) 后,程序可能出现的问题是( )→ A
A. 陷入死循环 B. 输出结果比原来大 C. 输出结果比原来小 D. 输出结果不受影响
n = 0 时原循环不进入;改成 >= 0 后进入,走偶数分支 ++x,而 n = 0/2 仍是 0,永远不满足 n < 0 → 死循环。
20. 当输入为 6 时,输出为( )→ C
A. 3 3 B. 4 2 C. 4 3 D. 5 2
6 = 110₂:n=6 偶 → x=2, n=3;n=3 奇 → x=3, y=2, n=1;n=1 奇 → x=4, y=3 → 4 3。
21. 若输入 n 依次取遍 0,1,…,2³¹−1,则输出第二个数恰好为 2 的次数为( )→ C
A. 16 B. 30 C. 31 D. 32
y = 2 ⟺ 二进制中恰有 1 个 1 ⟺ n 是 2 的幂。0 ~ 2³¹−1 中是 2⁰…2³⁰ 共 31 个(别把 2³¹ 算进去,它已超出范围)。
程序(2):高精度加法
int a[100007], b[100007], c[100007], carry[100007];
// 读入两个字符串,倒序存入 a[]、b[](低位在前)
carry[0] = 0;
for (int i = 0; i < max(a_len, b_len) + 1; i++) {
c[i] = a[i] + b[i] + carry[i]; // 第 21 行
if (c[i] >= 10) { // 第 22 行
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];
程序功能:非负整数高精度加法。抓手:输出固定为 max(a 位数, b 位数) + 1 位,因此高位经常出现前导零——本组 6 题全部围绕这一点设问。
22. 当输入为 123 456 时,程序输出为 0579。( )→ √
123 + 456 = 579,循环到 3+1 = 4 位,c[3] = 0 → 逆序输出 0579。
23. 假设输入的两个数均不含前导零,则输出也一定不会含有前导零。( )→ ×
只要两数位数相同且最高位无进位就会产生前导零,例如 111 + 222 = 333,输出 0333。
24. 将第 21 行改为 c[i]=a[i]+b[i]; 后,程序输出的结果一定比原来的结果小。( )→ ×
丢掉进位后,等于 10 的位不再减 10 进位。例如 5 + 5:原程序输出 10,改后 c[0] = 10,输出 010,数值相等而非更小。
25. 当输入为 12345 678 时,输出为( )→ B
A. 012923 B. 013023 C. 13023 D. 130230
12345 + 678 = 13023,共 6 位,最高位补 0 → 013023。
26. 将第 22 行 if (c[i]>=10) 改为 if (c[i]>10) 后,输入 95 15 时输出为( )→ A
A. 01010 B. 110 C. 140 D. 1410
个位 5+5 = 10、十位 9+1 = 10,都不满足 >10,于是不进位也不减 10:c[0] = 10、c[1] = 10、c[2] = 0 → 输出 0 10 10 拼成 01010。这题考的是「你是否真的理解判断条件在干什么」。
27. 输入两个数均为 n 位正整数(无前导零),和小于 10ⁿ,则输出字符串一定满足( )→ C
A. 第一个字符一定不为 ‘0’ B. 长度一定为 n C. 长度一定为 n+1,且第一个字符为 ‘0’ D. 长度可能为 n+2
和 < 10ⁿ 说明最高位没有进位,c[n] = 0,而循环固定走到 n+1 位 → 长度 n+1、首字符为 0。
程序(3):右截断素数 DFS
bool check_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;
void search_result(int x) {
if (!check_prime(x)) return;
if (x >= n) { cout << x << endl; return; }
for (int i = 0; i <= 9; i++) // 第 17 行
search_result(x * 10 + i);
}
int main() {
cin >> n;
for (int i = 1; i <= 9; i++) search_result(i);
return 0;
}
程序功能:从 1~9 出发,每次在末尾追加一位数字,要求每一步得到的数都必须是质数;一旦 ≥ n 就输出并停止深入。这类数称为右截断素数。注意输出顺序是 DFS 搜索序,不是从小到大。
28. 当输入为 10 时,程序的输出共有 10 行。( )→ ×
n = 10 时输出 23、29、31、37、53、59、71、73、79 共 9 行。
29. 若输入的 n 不大于 5,则程序的输出中一定包含 5。( )→ √
5 本身是质数且 5 ≥ n,一定被输出。
30. 若 n 大于 10,将第 17 行改为 for (int i=1;i<=9;i+=2) 后,输出结果一定不变。( )→ √
n > 10 时输出的都大于 10,而大于 10 的质数个位只能是 1、3、7、9(偶数或 5 结尾必被整除),追加偶数/5 分支永远产生不了新答案,故结果不变。
31. 当输入为 24 时,程序输出的第 3 行为( )→ B
A. 23 B. 29 C. 31 D. 239
搜索顺序:从 2 出发 → 23(< 24,继续)→ 233、239(第 1、2 行)→ 回到 2 的最后一个分支 29(≥ 24,第 3 行)。所以第 3 行是 29,不是按大小排的 31。
32. 下列关于该程序输出的说法中,正确的是( )→ D
A. 输出的数一定按从小到大排列(错:DFS 序,如 233、239、29) B. 随着 n 增大输出行数一定不会增加(错) C. 输出数的个位只可能是 3 或 7(错:还可能是 1、9,如 31、59) D. 输出的每个 ≥ 10 的数,删去末位后一定是质数(对:这是右截断素数的定义)
33. 当输入为 200 时,程序输出的行数为( )→ C
A. 12 B. 13 C. 14 D. 15
输出的是三位右截断素数,共 14 个:233、239、293、311、313、317、373、379、593、599、719、733、739、797。这是全卷最费时的一题——要么熟悉这类数的规律,要么把每个两位质数再往后接一位逐个判质数。
四、完善程序(单选题,每小题 3 分,共计 30 分)
程序(1):mn 进制转 n 进制(34–38)
题意:给定 n、m,再给定一个 mn 进制下的数 A(数位从高位到低位给出),把它转化为 n 进制并按同样顺序输出。程序采用「逐位处理」的方法:每读入一位 x,就把已有结果整体后移一位(等价于 ×n)并乘以 m,再加上 x,最后统一进位。
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--;
34. ①处应填( )→ D A. b[j]*n B. b[j]*m C. b[j-1]*n D. b[j-1]*m
数组在 n 进制下存储,下标整体 +1 就是 ×n,再乘 m 即 b[j-1]*m。
35. ②处应填( )→ B A. x*n B. x C. 0 D. m
新读入的一位直接放进个位。
36. ③处应填( )→ D A. b[j]/m B. b[j]%n C. b[j]%m D. b[j]/n
进位时把商加到高位。
37. ④处应填( )→ B A. b[j]/m B. b[j]%n C. b[j]%m D. b[j]/n
当前位保留模 n 的余数。
38. ⑤处应填( )→ C 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
去掉高位前导零,但 len > 1 保证至少保留一位(结果可能就是 0)。
程序(2):平衡分割(39–43)
题意:给定长度为 n 的字符串,每个字符都是一个十六进制数位(例如 016A 表示 0、1、6、10)。选 k 个切分位置把它分成 k+1 段(1 ≤ k < n),计算每段的平均值 b₀…bₖ,目标是让这些平均值的最大值与最小值之差尽可能小,输出该最小值(保留 6 位小数)。2 ≤ n ≤ 20,字符只可能是 0~9 或 A~F。
int get_val(char c) { return ①; }
void split(int l, int cnt, double minb, double maxb) {
if (l > n) {
if (cnt == 0) return;
ans = min(ans, maxb - minb);
return;
}
int sum = 0;
for (②) {
sum += ③;
double nwb = ④;
split(⑤);
}
}
int main() {
cin >> n >> s + 1;
split(1, -1, 1e100, -1e100);
cout << fixed << setprecision(6) << ans;
}
39. ①处应填( )→ A
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~F,必须按十六进制换算:’A’ 应得到 10。B 会得到 0,C 把数字整体 +1,D 得到 9,都不对。
40. ②处应填( )→ A
A. int r = l; r <= n; r++ B. int r = l; r < n; r++ C. int r = 1; r <= n; r++ D. int r = l; r++ < n
段末位置 r 必须能取到 n,否则最后一段无法收尾、递归终点 l > n 永远达不到,ans 不会被更新。B、D 都停在 n−1;C 每次从 1 开始,段就乱了。
41. ③处应填( )→ A
A. get_val(s[r]) B. get_val(s[r-1]) C. s[r-1] D. s[r]
配合 ② 的 r 从 l 到 n,累加当前字符的数值。B 首轮会取到上一段末尾的 s[l−1];C、D 直接加 ASCII 码——题干那句「假定字符采用 ASCII 编码」正是给这两个选项准备的烟雾弹。
42. ④处应填( )→ B
A. sum/(r-l+1) B. 1.0*sum/(r-l+1) C. 1.0*sum/(r-l) D. sum*1.0/n
平均值是小数(输出保留 6 位),必须用浮点除法;A 的整数除法会截断。C 分母少 1,D 分母用 n 不对。
43. ⑤处应填( )→ A
A. r+1, cnt+1, min(minb,nwb), max(maxb,nwb) B. r, cnt+1, minb, maxb C. r+1, cnt, nwb, nwb D. r, cnt, min(minb,nwb), max(maxb,nwb)
下一段从 r+1 开始;cnt 记录段数 − 1(初值 −1),每分出一段就 +1,终态 cnt == 0 表示一刀没切(只有 1 段),按题意 k ≥ 1 舍去;同时更新已见平均值的最小/最大值。
⚠️ 重要更正:网传解析给出的 39–43 答案(如 B D C A D)与卷面原文不符,多半是按想象中的空白位置作答。本文已对照原卷逐空验证,正确答案为 A A A B A。
五、写在最后
2026 年这套 J 组初赛知识点不偏、计算量偏大:纯记忆性的计算机常识题一道没有,全部是算法与数学类;区分度主要来自细心程度。
建议复盘时重点盯三类题目——需要手工模拟的(第 8 题 BFS)、需要理解输出格式的(高精度前导零)、需要理清搜索顺序的(右截断素数 DFS);另外 39–43 的平衡分割是本卷审查最密集的部分,值得把程序整体重写一遍。
预祝各位同学初赛取得好成绩,复赛再见!



