GESP 客观题评测系统

试卷解析 · 理解每一步

普及组 CSP-J 2026 初赛模拟卷 8

CSPJ-2026-R1-Mock-8

试卷解析总览,可直接查看每题答案与解析。

一、单项选择题

第 1 题(单选题,2 分)

CCF 的中文全称是( )。

A.
中国计算机协会
B.
中国计算机行会
C.
中国计算机学会
D.
中国计算机公会

正确答案C

解析详情
答案 C计算机组织与行业机构
思路与推导
  1. CCF 是 China Computer Federation 的缩写,中文名称为“中国计算机学会”。

第 2 题(单选题,2 分)

在 Linux 终端中,若当前目录下有一个空目录 `tmp`,删除该空目录可以使用命令( )。

A.
`cp tmp`
B.
`mkdir tmp`
C.
`touch tmp`
D.
`rmdir tmp`

正确答案D

解析详情
答案 DLinux 目录操作
思路与推导
  1. `rmdir tmp` 用于删除空目录;`mkdir` 创建目录,`touch` 创建文件或更新时间戳,`cp` 用于复制。

第 3 题(单选题,2 分)

表达式 `a * (b + c) * d` 的后缀形式是( )。

A.
`a b c d * + *`
B.
`a b c + * d *`
C.
`a * b c + * d`
D.
`b + c * a * d`

正确答案B

解析详情
答案 B中缀表达式转后缀表达式
思路与推导
  1. 先把 `b+c` 写成 `b c +`,再依次与 `a`、`d` 相乘,得到 `a b c + * d *`。后缀式中运算符出现在两个操作数之后,不需要括号。

第 4 题(单选题,2 分)

下列名称中,不能作为 C++ 变量名的是( )。

A.
`2sum`
B.
`sum2`
C.
`_count`
D.
`value_count`

正确答案A

解析详情
答案 AC++ 标识符
思路与推导
  1. C++ 标识符可以由字母、数字和下划线组成,但不能以数字开头,因此 `2sum` 非法。

第 5 题(单选题,2 分)

二进制数 `00101100` 和 `00010101` 的和是( )。

A.
`00101000`
B.
`01000001`
C.
`01000100`
D.
`00111000`

正确答案B

解析详情
答案 B二进制加法
思路与推导
  1. `00101100` 为 44,`00010101` 为 21,二者之和为 65;65=64+165=64+1,对应八位二进制数 `01000001`。

第 6 题(单选题,2 分)

微型计算机在工作中电源突然中断,再次通电后数据不能恢复的是( )。

A.
ROM 和 RAM 中的信息
B.
ROM 中的信息
C.
RAM 中的信息
D.
硬盘中的信息

正确答案C

解析详情
答案 C易失性存储器
思路与推导
  1. RAM 依靠持续供电保存当前数据,断电后其中的信息会丢失;ROM 和硬盘属于非易失性存储,重新通电后原有内容仍可保留。

第 7 题(单选题,2 分)

从一个 4×44\times4 的棋盘(不可旋转)中选取不在同一行也不在同一列上的两个方格(不计顺序),有( )种方法。

A.
72
B.
144
C.
256
D.
128

正确答案A

解析详情
答案 A组合计数与容斥
思路与推导
  1. 任取两格有 (162)=120\binom{16}{2}=120 种;同一行有 4(42)=244\binom{4}{2}=24 种,同一列也有 24 种,且两类不会重合。因此所求为 120−24−24=72120-24-24=72。

第 8 题(单选题,2 分)

执行下面的 C++ 代码后,输出结果是( )。

int x = 3;
int &r = x;
r += 4;
cout << x;
A.
3
B.
4
C.
6
D.
7

正确答案D

解析详情
答案 DC++ 引用
思路与推导
  1. `r` 是变量 `x` 的引用,对 `r` 加 4 就是直接把 `x` 从 3 修改为 7,因此输出 7。

第 9 题(单选题,2 分)

同时掷出 3 枚完全相同的六面骰子,每枚骰子上有 1 到 6 的数字。将得到的点数排序后,有( )种不同的结果。

A.
208
B.
56
C.
216
D.
120

正确答案B

解析详情
答案 B可重复组合
思路与推导
  1. 排序后的结果等价于从 1~6 中可重复地选 3 个数且不计顺序。由可重复组合公式,结果数为 (6+3−13)=(83)=56\binom{6+3-1}{3}=\binom{8}{3}=56。

第 10 题(单选题,2 分)

一个初始为空的队列依次执行 `push(4)`、`push(7)`、`pop()`、`push(9)`。此时从队首到队尾的元素依次为( )。

A.
7,9
B.
9,7
C.
4,9
D.
4,7,9

正确答案A

解析详情
答案 A队列操作
思路与推导
  1. 队列先进先出。压入 4、7 后弹出队首 4,再压入 9,剩余元素从队首到队尾为 7、9。

第 11 题(单选题,2 分)

采用 8 位二进制补码表示的有符号整数中,最小值的编码是( )。

A.
`10000000`
B.
`11111111`
C.
`01111111`
D.
`00000000`

正确答案A

解析详情
答案 A有符号整数的补码表示
思路与推导
  1. 8 位补码能够表示的范围是 −27-2^7 到 27−12^7-1。最小值 -128 的补码编码为 `10000000`。

第 12 题(单选题,2 分)

前序遍历序列与后序遍历序列相同的二叉树为( )。

A.
非叶节点只有左子树的二叉树
B.
只有根节点的二叉树
C.
根节点无右子树的二叉树
D.
非叶节点只有右子树的二叉树

正确答案B

解析详情
答案 B二叉树遍历
思路与推导
  1. 前序遍历先访问根,后序遍历最后访问根;只要还有其他节点,两序列中根的位置就不同。因而两序列完全相同只可能是仅有根节点的二叉树。

第 13 题(单选题,2 分)

下面有关数制的式子中,正确的是( )。

A.
(A2B.C5)16=(101000101011.01011100)2(A2B.C5)_{16}=(101000101011.01011100)_2
B.
(2)8×(6)8=(14)8(2)_8\times(6)_8=(14)_8
C.
(110010)2+(16)10=(1000100)2(110010)_2+(16)_{10}=(1000100)_2
D.
(1000)2=(8)8(1000)_2=(8)_8

正确答案B

解析详情
答案 B不同进制的运算与转换
思路与推导
  1. 八进制中 (2)8×(6)8=1210=148(2)_8\times(6)_8=12_{10}=14_8。例如 (1000)2=810=108(1000)_2=8_{10}=10_8,并不是 (8)8(8)_8,故 B 正确。

第 14 题(单选题,2 分)

若对于所有规模为 nn 的输入,一个算法均恰好进行( )次运算,则可以说该算法的时间复杂度为 O(2n)O(2^n)。

A.
2n+12^{n+1}
B.
3n3^n
C.
n×2nn\times2^n
D.
22n2^{2n}

正确答案A

解析详情
答案 A渐进时间复杂度
思路与推导
  1. 2n+1=2⋅2n2^{n+1}=2\cdot2^n,与 2n2^n 只差常数因子,所以属于 O(2n)O(2^n)。其余各项与 2n2^n 的比值分别为 (3/2)n(3/2)^n、nn 和 2n2^n,都不受常数约束。

第 15 题(单选题,2 分)

若 f0=0f_0=0,f1=1f_1=1,fn+1=(fn+fn−1)/2f_{n+1}=(f_n+f_{n-1})/2,则随着 ii 的增大,fif_i 将接近于( )。

A.
1/21/2
B.
2/32/3
C.
(5−1)/2(\sqrt5-1)/2
D.
11

正确答案B

解析详情
答案 B线性递推数列极限
思路与推导
  1. 特征方程为 2r2−r−1=02r^2-r-1=0,根为 11 和 −1/2-1/2。由 f0=0,f1=1f_0=0,f_1=1 得 fn=23−23(−12)nf_n=\frac{2}{3}-\frac{2}{3}(-\frac{1}{2})^n;振荡项趋于 0,所以极限为 2/32/3。

二、阅读程序(1)

1 | #include <iostream>
2 | using namespace std;
3 | int rSum(int j) {
4 |     int sum = 0;
5 |     while (j != 0) {
6 |         sum = sum * 10 + (j % 10);
7 |         j = j / 10;
8 |     }
9 |     return sum;
10 | }
11 | int main() {
12 |     int n, m;
13 |     cin >> n >> m; // 保证输入为正整数,但不大于 10^9
14 |     for (int i = n; i < m; i++)
15 |         if (i == rSum(i)) cout << i << ' ';
16 |     return 0;
17 | }

第 16 题(判断题,1 分)

主函数中的 `for` 循环总共执行 m−nm-n 次。( )

正确答案错误

解析详情
答案 错误for 循环边界
思路与推导
  1. 循环变量取满足 n≤i<mn\le i<m 的整数;仅当 n≤mn\le m 时才执行 m−nm-n 次。输入没有保证 n≤mn\le m,若 n>mn>m,循环执行 0 次而不是负数次。

第 17 题(判断题,2 分)

`rSum` 这个函数的返回值 `sum` 一定不会大于 jj。( )

正确答案错误

解析详情
答案 错误十进制数位反转
思路与推导
  1. `rSum` 实际返回十进制数位反转结果,反转后可能变大。例如 `rSum(12)=21`,有 21>1221>12。

第 18 题(判断题,2 分)

若 n=1n=1、mm 足够大,则输出个数的量级逐渐趋近于 O(m1/2)O(m^{1/2})。( )

正确答案正确

解析详情
答案 正确回文数计数
思路与推导
  1. 程序输出十进制回文数。一个不超过 mm 的 dd 位回文数由前 ⌈d/2⌉\lceil d/2\rceil 位唯一确定,所需自由位约为总位数的一半,因此累计数量与 m\sqrt{m} 同量级。

第 19 题(判断题,2 分)

输入任意两个取值范围为 [1,100][1,100] 的整数,输出个数都不超过 100。( )

正确答案正确

解析详情
答案 正确输出次数上界
思路与推导
  1. 循环只检查区间 [n,m)[n,m) 内的整数;当 n,m∈[1,100]n,m\in[1,100] 时,最多检查 11 到 9999 共 99 个数,输出又只是其中的回文数子集,所以不超过 100。

第 20 题(单选题,3 分)

若输入 `190 230`,总共会输出( )个数。

A.
1
B.
2
C.
3
D.
4

正确答案D

解析详情
答案 D程序模拟与回文数
思路与推导
  1. 循环检查 190≤i<230190\le i<230。其中满足 `i == rSum(i)` 的数依次为 `191、202、212、222`,共输出 4 个。

第 21 题(单选题,3 分)

假设 nn 和 mm 是相同量级(m=O(n)m=O(n)),则程序的时间复杂度是( )。

A.
O(n)O(n)
B.
O(nlog⁡n)O(n\log n)
C.
O(n3/2)O(n^{3/2})
D.
O(n2)O(n^2)

正确答案B

解析详情
答案 B循环与数位处理复杂度
思路与推导
  1. 当 m=O(n)m=O(n) 时,外层 `for` 检查 m−n=O(n)m-n=O(n) 个整数。`rSum(i)` 每次通过除以 10 处理 O(log⁡n)O(\log n) 位,因此总时间为 O(nlog⁡n)O(n\log n)。

二、阅读程序(2)

1 | #include <iostream>
2 | #include <string>
3 | using namespace std;
4 | int main() {
5 |     string s;
6 |     char m1, m2;
7 |     getline(cin, s);
8 |     m1 = ' ';
9 |     m2 = ' ';
10 |     for (int i = 0; i < s.length(); i++) {
11 |         if (s[i] > m1) {
12 |             m2 = m1;
13 |             m1 = s[i];
14 |         } else if (s[i] > m2)
15 |             m2 = s[i];
16 |     }
17 |     cout << int(m1) << ' ' << int(m2) << endl;
18 |     return 0;
19 | }

第 22 题(判断题,1 分)

`getline()` 会将一整行连带空格一起输入到字符串中。( )

正确答案正确

解析详情
答案 正确C++ getline 输入
思路与推导
  1. `getline(cin, s)` 读取到换行符为止,行内的空格会作为普通字符存入 `s`,只有作为分隔符的换行符不会存入。

第 23 题(判断题,2 分)

输出的两个整数不可能相同。( )

正确答案错误

解析详情
答案 错误最大与次大字符维护
思路与推导
  1. 程序没有要求两个字符互异。若最大字符重复出现,例如输入 `zz`,第一次令 `m1='z'`,第二次会令 `m2='z'`,最终两个整数都为 122。

第 24 题(判断题,2 分)

删去 `else` 这几个字符,则可能出现 m2>m1m2>m1 的情况。( )

正确答案错误

解析详情
答案 错误条件分支与不变量
思路与推导
  1. 删去 `else` 后,第二个 `if` 也会在更新 `m1` 后执行;此时最多把 `m2` 更新为新的 `m1`。因此始终仍有 `m2<=m1`,不可能出现 `m2>m1`。

第 25 题(判断题,2 分)

若输入长度为 10 且仅含小写字母的随机字符串,则输出结果中 m2m2 的值越大,其出现的可能性越小。( )

正确答案错误

解析详情
答案 错误次大次序统计量
思路与推导
  1. m2m2 是 10 个字符中允许重复的第二大字符,随机样本通常集中在较大的字母。例如 m2=′a′m2='a' 要求至多一个字符大于 `a`,条件极苛刻;较大的 m2m2 反而可由更多字符串产生。

第 26 题(单选题,3 分)

维护 `m1` 和 `m2` 的过程最接近( )。

A.
选择排序
B.
插入排序
C.
冒泡排序
D.
计数排序

正确答案B

解析详情
答案 B插入排序思想
思路与推导
  1. 每读入一个字符,程序把它插入当前由 `m1、m2` 表示的降序前两名,并在必要时把旧 `m1` 后移到 `m2`。这种逐个插入到已有有序序列的过程最接近插入排序。

第 27 题(单选题,3 分)

若输入 `mxoj is the best online judge`,输出为( )。

A.
`120 120`
B.
`120 119`
C.
`120 117`
D.
`122 120`

正确答案C

解析详情
答案 C字符串扫描与 ASCII 码
思路与推导
  1. 逐字符维护前两大字符时,字符串中的最大字符是 `x`,ASCII 码为 120;次大字符是 `u`,ASCII 码为 117。因此输出 `120 117`。

二、阅读程序(3)

1 | #include <iostream>
2 | using namespace std;
3 | int n, p, a;
4 | int main() {
5 |     cin >> n; // 保证输入在 int 范围内
6 |     while (n > 1) {
7 |         for (p = 2; p <= n; p++)
8 |             if (n % p == 0) break;
9 |         for (a = 0; n % p == 0; n /= p) a++;
10 |         cout << p << ' ' << a << endl;
11 |     }
12 |     return 0;
13 | }

第 28 题(判断题,2 分)

若输入正整数,则程序在有限步内一定会结束。( )

正确答案正确

解析详情
答案 正确质因数分解循环终止性
思路与推导
  1. 当 n>1n>1 时,内层总能找到一个整除 nn 的 pp(最迟找到 p=np=n);随后至少执行一次 `n /= p`,使正整数 nn 严格减小,最终到达 1。

第 29 题(判断题,2 分)

如有输出,输出的 aa 永远是正的。( )

正确答案正确

解析详情
答案 正确质因数指数统计
思路与推导
  1. 只有找到因子 pp 后才进入第二个 `for`,此时 `n % p == 0` 至少成立一次,所以 `a` 至少从 0 增加到 1 后才输出。

第 30 题(判断题,2 分)

最坏情况下程序的时间复杂度为 O(n2)O(n^2)。( )

正确答案正确

解析详情
答案 正确嵌套循环复杂度上界
思路与推导
  1. 按直接上界估计,外层 `while` 至多执行 O(n)O(n) 轮,每轮寻找因子的 `for` 至多检查 O(n)O(n) 个候选,故可得 O(n2)O(n^2) 上界。实际上每轮会除尽一个质因子,还能给出更紧的上界,但不影响该大 O 断言成立。

第 31 题(判断题,2 分)

输出的 pp 是逐行严格递增的。( )

正确答案正确

解析详情
答案 正确质因数分解顺序
思路与推导
  1. 每次找到当前 nn 的最小因子 pp 后,第二个循环会把该因子的所有幂全部除尽。所以下一轮找到的质因子必然大于当前 pp,输出的 pp 逐行严格递增。

第 32 题(单选题,3 分)

若输入 72,则共输出( )个数。

A.
1
B.
2
C.
3
D.
4

正确答案B

解析详情
答案 B整数质因数分解
思路与推导
  1. 72=23×3272=2^3\times3^2。程序对每种不同质因子输出一行,先输出 `2 3`,再输出 `3 2`,因此共输出 2 行结果。

第 33 题(单选题,3 分)

对 n=2..100n=2..100 依次运行以上程序,输出的总行数最接近( )。

A.
50
B.
100
C.
150
D.
200

正确答案C

解析详情
答案 C不同质因子个数的累计计数
思路与推导
  1. 对每个 nn,输出行数等于其不同质因子个数 ω(n)\omega(n)。枚举 2≤n≤1002\le n\le100 并累加可得 ∑ω(n)=171\sum\omega(n)=171;它与 150 相差 21,与 200 相差 29,所以最接近 150。

三、完善程序(1)子矩阵

输入一个 n1×m1n1\times m1 的矩阵 aa 和一个 n2×m2n2\times m2 的矩阵 bb,判断 aa 中是否存在与 bb 相等的连续子矩阵;若存在,输出所有子矩阵左上角坐标,否则输出 `There is no answer`。

1 | #include <iostream>
2 | using namespace std;
3 | const int SIZE = 50;
4 | int n1, m1, n2, m2, a[SIZE][SIZE], b[SIZE][SIZE];
5 | int main() {
6 |     int i, j, k1, k2;
7 |     bool good, haveAns;
8 |     cin >> n1 >> m1;
9 |     for (i = 1; i <= n1; i++)
10 |         for (j = 1; j <= m1; j++) cin >> a[i][j];
11 |     cin >> n2 >> m2;
12 |     for (i = 1; i <= n2; i++)
13 |         for (j = 1; j <= m2; j++) cin >> b[i][j];
14 |     ①;
15 |     for (i = 1; i <= n1 - n2 + 1; i++)
16 |         for (j = 1; j <= ②; j++) {
17 |             ③;
18 |             for (k1 = 1; k1 <= n2; k1++)
19 |                 for (k2 = 1; k2 <= m2; k2++) {
20 |                     if (④ != b[k1][k2])
21 |                         good = false;
22 |                 }
23 |             if (good) {
24 |                 cout << i << ' ' << j << endl;
25 |                 ⑤;
26 |             }
27 |         }
28 |     if (!haveAns)
29 |         cout << "There is no answer" << endl;
30 |     return 0;
31 | }

第 34 题(单选题,3 分)

① 处应填( )。

A.
haveAns = true
B.
haveAns = false
C.
good = true
D.
good = false

正确答案B

解析详情
答案 B状态变量初始化
思路与推导
  1. `haveAns` 记录是否曾找到匹配子矩阵。在开始枚举任何左上角坐标前尚无答案,因此必须初始化为 `false`,之后找到匹配时再改为 `true`。

第 35 题(单选题,3 分)

② 处应填( )。

A.
n1 + n2 - 1
B.
m1 - m2 + 1
C.
n1 - m1 + 1
D.
m1 + m2 - 1

正确答案B

解析详情
答案 B子矩阵枚举边界
思路与推导
  1. 宽为 m2m2 的子矩阵若从第 jj 列开始,最右列为 j+m2−1j+m2-1,需满足 j+m2−1≤m1j+m2-1\le m1。因此 jj 的上界是 m1−m2+1m1-m2+1。

第 36 题(单选题,3 分)

③ 处应填( )。

A.
haveAns = true
B.
haveAns = false
C.
good = true
D.
good = false

正确答案C

解析详情
答案 C候选子矩阵匹配状态
思路与推导
  1. 每枚举一个新的左上角 `(i,j)`,都应先假设该候选完全匹配,即令 `good = true`;随后只要发现任一对应元素不等,就把 `good` 置为 `false`。

第 37 题(单选题,3 分)

④ 处应填( )。

A.
a[i + k1 - 1][j + k2 - 1]
B.
a[i + k1][j + k2]
C.
a[i - k1 - 1][j - k2 - 1]
D.
a[i - k1][j - k1]

正确答案A

解析详情
答案 A二维数组下标映射
思路与推导
  1. `b[k1][k2]` 对应以 `(i,j)` 为左上角的子矩阵第 `k1` 行、第 `k2` 列。由于数组从 1 开始编号,在 `a` 中的位置应为 `a[i+k1-1][j+k2-1]`。

第 38 题(单选题,3 分)

⑤ 处应填( )。

A.
haveAns = true
B.
haveAns = false
C.
good = true
D.
good = false

正确答案A

解析详情
答案 A匹配结果标记
思路与推导
  1. 进入 `if (good)` 表明当前子矩阵与 `b` 完全相等,程序已经输出一个答案,所以应执行 `haveAns = true`。这样最后的 `if (!haveAns)` 就不会误报无解。

三、完善程序(2)高精度加法

输入两个位数不超过 100 且首位不是 0 的大整数。使用数组的每个元素存储一位数,输出两数之和。

1 | #include <iostream>
2 | #include <string>
3 | #define SIZE 200
4 | using namespace std;
5 |
6 | int x[2][SIZE]; // x[0]、x[1] 存放两个加数
7 |
8 | void converts(int d, string s) {
9 |     int i, len = ①;
10 |     for (i = 0; i < len; i++)
11 |         x[d][i] = s[len - i - 1] - '0';
12 | }
13 |
14 | void add() {
15 |     for (int i = 0; i < SIZE; i++) {
16 |         x[0][i] += x[1][i];
17 |         if (②) {
18 |             x[0][i + 1]++;
19 |             ③;
20 |         }
21 |     }
22 | }
23 |
24 | void print(int d) {
25 |     int i;
26 |     for (i = SIZE - 1; i > 0; i--)
27 |         if (x[d][i]) ④;
28 |     for (; i >= 0; i--) cout << x[d][i];
29 |     cout << endl;
30 | }
31 |
32 | int main() {
33 |     string s1, s2;
34 |     cin >> s1 >> s2;
35 |     converts(0, s1);
36 |     converts(1, s2);
37 |     add();
38 |     ⑤;
39 |     return 0;
40 | }

第 39 题(单选题,3 分)

① 处应填( )。

A.
0
B.
d
C.
s.length()
D.
s.length() - 1

正确答案C

解析详情
答案 C字符串逆序转数位数组
思路与推导
  1. 循环需要处理字符串中的每一位,故 `len` 应等于 `s.length()`。随后用 `s[len-i-1]` 从末位向首位读取,使个位存入 `x[d][0]`。

第 40 题(单选题,3 分)

② 处应填( )。

A.
x[0][i] >= 10
B.
x[0][i] > 10
C.
x[1][i] >= 10
D.
x[1][i] > 10

正确答案A

解析详情
答案 A高精度加法进位条件
思路与推导
  1. 相加结果保存在 `x[0][i]`;十进制某位达到 10 就必须向 `x[0][i+1]` 进 1,因此条件是 `x[0][i] >= 10`。值恰好为 10 也要进位。

第 41 题(单选题,3 分)

③ 处应填( )。

A.
x[0][i] += 10
B.
x[0][i] -= 10
C.
x[1][i] += 10
D.
x[1][i] -= 10

正确答案B

解析详情
答案 B高精度加法当前位归一化
思路与推导
  1. 发生进位后已经执行 `x[0][i+1]++`,当前位应保留除以 10 的余数。两位十进制数位加进位后最大为 19,所以执行 `x[0][i] -= 10` 即可。

第 42 题(单选题,3 分)

④ 处应填( )。

A.
return
B.
continue
C.
cout << x[d][i]
D.
break

正确答案D

解析详情
答案 D高精度数输出与前导零
思路与推导
  1. 循环从最高下标向下寻找第一个非零数位;找到后应 `break`,保留当前下标 `i`,再由下一循环从该位输出到个位。这样可以跳过所有前导零。

第 43 题(单选题,3 分)

⑤ 处应填( )。

A.
print(0)
B.
print(1)
C.
print(2)
D.
print(3)

正确答案A

解析详情
答案 A高精度加法结果存储
思路与推导
  1. `add()` 将 `x[1]` 的各位累加到 `x[0]`,并把进位也写回 `x[0]`,所以最终和完整存放在第 0 行,应调用 `print(0)`。