试卷解析 · 理解每一步
普及组 CSP-J 2026 初赛模拟卷 9
CSPJ-2026-R1-Mock-9
试卷解析总览,可直接查看每题答案与解析。
第 1 题(单选题,2 分)
在 C++ 中使用 `sort` 函数前,通常需要包含的头文件是( )。
正确答案B
解析详情
`sort` 属于标准算法库,声明在头文件 `<algorithm>` 中。
第 2 题(单选题,2 分)
客户端和服务器之间完成 TCP 连接建立需要通过( )次握手。
正确答案C
解析详情
客户端发送 SYN,服务器回复 SYN+ACK,客户端再发送 ACK,共交换 3 次报文后建立 TCP 连接。
第 3 题(单选题,2 分)
下列( )两种语言都是典型的编译型语言。
正确答案D
解析详情
Pascal 和 C++ 的源程序通常先由编译器整体翻译为目标程序,再执行生成的程序,二者都是典型的编译型语言。
第 4 题(单选题,2 分)
二进制数 对应的八进制数是( )。
正确答案C
解析详情
从小数点向右每 3 位分组并补零:。、,所以结果为 。
第 5 题(单选题,2 分)
公告只包含 A、B、C、D 四个字符,出现频率分别为 20%、30%、40%、10%。使用哈夫曼编码,( )的编码长度一定最短。
正确答案C
解析详情
先合并频率最低的 D(10%) 与 A(20%) 得 30%,再合并两个 30%,最后由 C(40%) 与 60% 的结点组成根。C 直接连在根下,码长为 1,必定最短。
第 6 题(单选题,2 分)
扫描一张 4 英寸 × 6 英寸的彩色照片,分辨率为 300 dpi,使用 24 位真彩色且不压缩,存储容量约为( )。
正确答案C
解析详情
像素数为 ,24 位即每像素 3 字节。容量为 字节,按二进制单位折算约 ,最接近 6.22MB。
第 7 题(单选题,2 分)
在 Linux 终端中,要在当前目录及其子目录的文本文件里递归查找字符串 `CSPJ`,最合适的命令是( )。
正确答案D
解析详情
`grep -R CSPJ .` 会从当前目录开始递归搜索包含指定字符串的文件内容。
第 8 题(单选题,2 分)
假设布尔变量 为真、 为假、 为真,那么表达式 的结果是( )。
正确答案A
解析详情
;。两部分取或得到真。
第 9 题(单选题,2 分)
在单链表中,指针 `p` 指向待删除结点的前驱,且 `p->next` 一定存在。正确删除 `p->next` 所指结点的代码是( )。
正确答案C
解析详情
先用 `q` 保存待删除结点,再让前驱 `p` 越过该结点指向 `q->next`,最后释放 `q`,因此 C 正确。
第 10 题(单选题,2 分)
一棵二叉树,中序遍历的结果为 `abc`,那么这棵二叉树有( )种不同的形态。
正确答案D
解析详情
固定 3 个结点的中序次序后,不同二叉树形态数为第 3 个卡特兰数:。
第 11 题(单选题,2 分)
给定数字 0、1、3、4、5、9,每个数字最多用一次,可能组成( )个 4 位偶数。
正确答案D
解析详情
末位为 0 时有 个;末位为 4 时,首位有 4 种非零选择,中间两位有 种,共 48 个。总数为 。
第 12 题(单选题,2 分)
以下代码的输出是( )。
int a = 5, b = 3, c = 0;
c = a++ + ++b;
cout << a << ' ' << b << ' ' << c;正确答案C
解析详情
「a++」 先参与运算取值 5,再使 「a=6」;「++b」 先使 「b=4」,再取值 4。因此 「c=5+4=9」,输出 「6 4 9」。
第 13 题(单选题,2 分)
定义 为 的各位数字之和。数字根 (直到结果不再变化),则 的结果是( )。
正确答案B
解析详情
,继续计算 ;1 已是个位数,因此 。
第 14 题(单选题,2 分)
在 NOI Linux 终端中,要删除名为 `old.exe` 的文件,应该使用命令( )。
正确答案B
解析详情
Linux 使用 「rm 文件名」 删除普通文件,因此删除 「old.exe」 的命令是 「rm old.exe」。
第 15 题(单选题,2 分)
以下代码的输出是( )。
const int N = 5;
int arr[N] = {10, 20, 30, 40, 50};
int *p = arr;
int sum = 0;
for (int i = 0; i < N; i++) {
sum += (*p)++;
}
cout << sum;正确答案C
解析详情
「p」 始终指向 「arr[0]」,循环中的 「(*p)++」 每次先把当前值加入 「sum」,再令该元素加 1。五次加入的值依次为 10、11、12、13、14,总和为 60。
二、阅读程序(1)
1 | #include <bits/stdc++.h>
2 | #define int long long
3 | using namespace std;
4 | int f(int x) {
5 | int res = 0;
6 | while (x) {
7 | res += x % 10;
8 | x /= 10;
9 | }
10 | return res;
11 | }
12 | int solve1(int x) {
13 | if (x < 10) return x;
14 | return solve1(f(x));
15 | }
16 | int solve2(int x) {
17 | return (x - 1) % 9 + 1;
18 | }
19 | signed main() {
20 | int n;
21 | cin >> n;
22 | cout << solve1(n) << ' ' << solve2(n) << endl;
23 | return 0;
24 | }第 16 题(判断题,2 分)
输入 1234 时,输出结果为 `1 1`。( )
正确答案正确
解析详情
「f(1234)=10」,继续有 「f(10)=1」,所以 「solve1(1234)=1」;「solve2(1234)=(1234-1)%9+1=1」,输出为 「1 1」。
第 17 题(判断题,2 分)
输入的数为负数时,输出的两个数肯定不一致。( )
正确答案错误
解析详情
反例取 「x=-1」:「solve1(-1)」 因 「x<10」 直接返回 -1;C++ 中 「(-2)%9=-2」,故 「solve2(-1)=-1」,两个输出相同。
第 18 题(判断题,2 分)
将 `solve1()` 的内容改成下面的代码,其功能不变。( )
while (x >= 10) x = f(x);
return x;正确答案正确
解析详情
原函数在 「x>=10」 时递归调用 「solve1(f(x))」,直到 「x<10」 返回;循环版本重复执行同样的 「x=f(x)」,终止条件和最终返回值完全一致。
第 19 题(单选题,3 分)
若输入的 为一个身份证号码(保证没有 X),则下列说法中正确的是( )。
正确答案D
解析详情
「#define int long long」 使 「n」 为 64 位有符号整数;18 位身份证号码小于约 的上限。首次数位和至多 162,随后很快降为个位数,两个函数均可正常得到数字根。
第 20 题(单选题,4 分)
函数 `solve1()` 和 `solve2()` 的时间复杂度分别为( )。
正确答案A
解析详情
按命题预期只计数字和后的递归压缩层数,位数会从 迅速降到 量级,因此记为 ;公式法 「solve2」 只做常数次运算,为 。
若把 「f(n)」 扫描全部十进制位的代价计入,「solve1」 实际为 ,故答案 A 的复杂度口径需结合原卷确认。
二、阅读程序(2)
1 | #include <iostream>
2 | #include <iomanip>
3 | #include <cmath>
4 | using namespace std;
5 | const double ERR = 1e-7;
6 | const double CMP_EPS = 1e-12;
7 |
8 | int main() {
9 | double x;
10 | scanf("%lf", &x); // 保证输入是非负实数
11 | double left = 0, right = max(1.0, x);
12 | while (right - left > ERR) {
13 | double mid = (left + right) / 2;
14 | double diff = mid * mid - x;
15 | if (fabs(diff) <= CMP_EPS) {
16 | left = mid;
17 | break;
18 | }
19 | if (diff < 0) {
20 | left = mid;
21 | } else {
22 | right = mid;
23 | }
24 | }
25 | printf("%.6lf\n", left);
26 | return 0;
27 | }第 21 题(判断题,2 分)
该程序使用二分法求非负实数的算术平方根。( )
正确答案正确
解析详情
区间初始为 ,包含 ;每次根据 「mid*mid-x」 的正负保留含根的一半区间,最终 「left」 逼近 。
第 22 题(判断题,2 分)
将 `while` 循环改为 `while (right != left)`,程序也可以正常输出,但结果不够精确。( )
正确答案错误
解析详情
浮点数精度有限,区间很小时 「mid」 可能舍入成 「left」 或 「right」,赋值后区间不再缩小而两端仍不相等,「right != left」 可能导致死循环。
第 23 题(判断题,2 分)
若输入的数为 ,则该程序的时间复杂度为 。( )
正确答案正确
解析详情
初始区间长度为 ,每轮减半,迭代次数约为 。当 「ERR」 为常数且 时可写为 。
第 24 题(单选题,3 分)
当输入 0.625 时,输出结果是( )。
正确答案C
解析详情
程序二分逼近 ,而 。按 「%.6lf」 保留 6 位小数,输出 「0.790569」。
第 25 题(单选题,4 分)
`ERR` 的值修改为( ),会导致输出结果有误差。
正确答案A
解析详情
输出保留 6 位小数,要稳定舍入通常需把绝对误差控制到小于约 。
「ERR=1e-6」 时区间宽度仍可能造成末位舍入错误;其余阈值更小,精度更充分。
二、阅读程序(3)
1 | #include <bits/stdc++.h>
2 | using namespace std;
3 | typedef long long ll;
4 | const ll N = 21;
5 | ll n, m, S[N][N];
6 |
7 | int main() {
8 | cin >> n >> m; // 保证 n、m 是不大于 20 的正整数
9 | if (n < m) {
10 | cout << 0 << endl;
11 | return 0;
12 | }
13 | if (n == m && m == 0) {
14 | cout << 1 << endl;
15 | return 0;
16 | }
17 |
18 | for (int i = 1; i <= n; i++) S[i][1] = 1;
19 | for (int j = 2; j <= m; j++)
20 | for (int i = j; i <= n; i++)
21 | S[i][j] = S[i - 1][j - 1] + j * S[i - 1][j];
22 | cout << S[n][m] << endl;
23 | return 0;
24 | }第 26 题(判断题,2 分)
若输入 ,则程序输出结果为 26。( )
正确答案错误
解析详情
递推为 。由 、 得 ,不是 26。
第 27 题(判断题,2 分)
程序计算将 个不同元素划分成 个无序集合的方案数。( )
正确答案错误
解析详情
程序的递推 计算把 个不同元素划分为 个非空、无标号集合的方案数。
题干只说“ 个无序集合”,没有给出每个集合必须非空这一必要限制,描述不完整,因此按原卷答案判为错误。
第 28 题(判断题,2 分)
若将第 22 行改成下面的代码,则程序计算将 个不同元素划分到不超过 个非空集合的方案总数。( )
ll res = 0;
for (int i = 1; i <= m; i++) res += S[n][i];
cout << res << endl;正确答案正确
解析详情
「S[n][i]」 表示恰好划分为 个非空集合的方案数。将 到 的值相加,恰好覆盖划分为不超过 个非空集合的全部情况,且各情况互不重复。
第 29 题(单选题,4 分)
若输入 ,则程序输出结果为( )。
正确答案C
解析详情
递推到 可得 、,于是 。
第 30 题(单选题,4 分)
若将内层循环条件 `for (int i = j; i <= n; i++)` 改为 `for (int i = 1; i <= n; i++)`,则程序( )。
正确答案A
解析详情
数组为全局变量, 的状态初值均为 0;按 递增、 递增计算时,这些无效状态仍由零状态推出 0。它们虽被多算,却不会影响后续 的有效状态,所以结果不变。
三、完善程序(1)差分数组
(差分数组)给定一个长度为 、初始值全为 0 的序列。进行 次操作,每次把闭区间 中的所有数增加 ,最后输出整个序列。保证 。
1 | #include <iostream>
2 | #include <vector>
3 | using namespace std;
4 | int main() {
5 | int n, m;
6 | cin >> n >> m;
7 | vector<long long> diff(①, 0), a(n + 1, 0);
8 | for (int k = 0; k < ②; ++k) {
9 | int l, r;
10 | long long x;
11 | cin >> l >> r >> x;
12 | ③;
13 | ④;
14 | }
15 | for (int i = 1; i <= n; ++i) {
16 | a[i] = ⑤;
17 | cout << a[i] << (i == n ? '\n' : ' ');
18 | }
19 | return 0;
20 | }第 31 题(单选题,3 分)
① 处应填( )。
nn - 1n + 1n + 2正确答案D
解析详情
操作会访问 `diff[r+1]`,当 `r=n` 时需要访问下标 `n+1`,所以数组长度至少为 `n+2`。
第 32 题(单选题,3 分)
② 处应填( )。
nn + mmn * m正确答案C
解析详情
输入包含 `m` 次区间修改,因此操作循环应执行 `m` 次。
第 33 题(单选题,3 分)
③ 处应填( )。
diff[r] += xdiff[l] -= xa[l] += xdiff[l] += x正确答案D
解析详情
让区间从位置 `l` 开始增加 `x`,应执行 `diff[l] += x`。
第 34 题(单选题,3 分)
④ 处应填( )。
diff[r] -= xdiff[l + 1] -= xdiff[r + 1] += xdiff[r + 1] -= x正确答案D
解析详情
区间影响在 `r` 之后结束,因此应在 `r+1` 位置减去 `x`。
第 35 题(单选题,3 分)
⑤ 处应填( )。
diff[i - 1] + a[i]a[i - 1] + diff[i]a[i - 1] - diff[i]diff[i]正确答案B
解析详情
原数组等于差分数组的前缀和,所以 `a[i] = a[i-1] + diff[i]`。
三、完善程序(2)高精度除以单精度
当大数超过普通整数范围时,使用数组模拟手工除法,从高位到低位逐位计算,输出大数除以普通整数所得的商和余数。
1 | #include <iostream>
2 | #include <string>
3 | #define SIZE 209
4 | using namespace std;
5 | void converts(int *a, string s) {
6 | int i, len = s.size();
7 | for (i = 0; i < len; i++) a[i] = s[len - i - 1] - '0';
8 | for (; i < SIZE; i++) a[i] = 0;
9 | }
10 | void div(int *a, int n) {
11 | for (int i = SIZE - 1, c = 0; i >= 0; i--) {
12 | c = ①;
13 | a[i] = c / n;
14 | }
15 | }
16 |
17 | int mod(int *a, int n) {
18 | int r = 0;
19 | for (int i = SIZE - 1; i >= 0; i--)
20 | r = (r * 10 + a[i]) % n;
21 | return r;
22 | }
23 | void print(int *a) {
24 | int i;
25 | for (i = SIZE - 1; i > 0; i--)
26 | if (a[i] > 0) break;
27 | for (②) cout << a[i];
28 | cout << endl;
29 | }
30 | int x[SIZE];
31 |
32 | int main() {
33 | string s;
34 | int n;
35 | cin >> s >> n;
36 | ③;
37 | int r;
38 | ④;
39 | ⑤;
40 | print(x);
41 | cout << r << endl;
42 | return 0;
43 | }第 36 题(单选题,3 分)
① 处应填( )。
c / n + a[i]c % n + a[i]c / n * 10 + a[i]c % n * 10 + a[i]正确答案D
解析详情
处理当前十进制位前,应取上一前缀除以 「n」 的余数 「c%n」,乘 10 后拼接当前位 「a[i]」,即 「c=c%n*10+a[i]」;随后 「c/n」 就是当前商位。
第 37 题(单选题,3 分)
② 处应填( )。
i - 1; i >= 0; i--i - 1; i > 0; i--; i >= 0; i--; i > 0; i--正确答案C
解析详情
前一个循环结束时,「i」 已停在商的最高非零位;输出循环应复用当前 「i」,从该位一直打印到下标 0,因此初始化部分留空,条件为 「i>=0」。
第 38 题(单选题,3 分)
③ 处应填( )。
converts(x, n)converts(n, x)converts(x, s)converts(s, x)正确答案C
解析详情
「converts(int *a,string s)」 的第一个参数接收数字数组,第二个参数接收输入字符串。主程序应把字符串 「s」 逆序转换到数组 「x」,所以调用 「converts(x,s)」。
第 39 题(单选题,3 分)
④ 处应填( )。
mod(x, n)div(x, n)r = mod(x, n)r = div(x, n)正确答案C
解析详情
「mod(x,n)」 依据原被除数数组计算余数并返回,故先执行 「r=mod(x,n)」 保存余数。若先调用 「div」,数组 「x」 会被原地改写为商,之后无法得到原数的余数。
第 40 题(单选题,3 分)
⑤ 处应填( )。
mod(x, n)div(x, n)r = mod(x, n)r = div(x, n)正确答案B
解析详情
余数已由上一空保存到 「r」 后,需要调用 「div(x,n)」,从高位到低位把数组 「x」 原地改成商;随后 「print(x)」 才能输出正确的商。