GESP 客观题评测系统

试卷解析 · 理解每一步

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

CSPJ-2026-R1-Mock-4

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

一、单项选择题

(共 15 题,每题 2 分,共计 30 分;每题有且仅有一个正确选项)

第 1 题(单选题,2 分)

在 NOI Linux 的终端中,要列出当前目录下所有文件和文件夹的详细信息(包括权限、大小、修改时间等),应该使用命令( )。

A.
`ls`
B.
`ls -l`
C.
`ls -a`
D.
`ls -s`

正确答案B

解析详情
答案 BLinux 文件命令
思路与推导
  1. `ls -l` 使用长格式列出名称、权限、链接数、所有者、大小和修改时间等详细信息。

第 2 题(单选题,2 分)

执行下面代码后,输出结果为( )。

int a = 6, b = 3;
cout << ((a & b) | (a ^ b));
A.
1
B.
3
C.
7
D.
9

正确答案C

解析详情
答案 C位运算
思路与推导
  1. `6&3=2`,`6^3=5`,再计算 `2|5=7`,因此输出 7。

第 3 题(单选题,2 分)

在 C++ 中,表达式 `!(5 > 3) && (4 <= 4) || (2 != 2)` 的结果是( )。

A.
`true`
B.
`false`
C.
`1`
D.
编译错误

正确答案B

解析详情
答案 B逻辑运算
思路与推导
  1. `5 > 3` 为真,取反后为假;假与任何值进行 `&&` 仍为假,`2 != 2` 也为假,所以整个表达式为 `false`。

第 4 题(单选题,2 分)

关于单向链表,以下描述中正确的是( )。

A.
可以随机访问任意位置的元素
B.
插入和删除元素的时间复杂度都是 O(1)O(1)
C.
需要连续的存储空间
D.
每个节点包含数据和指向下一个节点的指针

正确答案D

解析详情
答案 D单向链表
思路与推导
  1. 单向链表的每个节点保存数据以及指向下一个节点的指针,节点不要求连续存储。

第 5 题(单选题,2 分)

对于有 nn 个节点的二叉树,其最小高度是( )。

A.
⌈log⁡2n⌉\lceil\log_2 n\rceil
B.
⌈log⁡2(n+1)⌉−1\lceil\log_2(n+1)\rceil-1
C.
n−1n-1
D.
1

正确答案B

解析详情
答案 B二叉树高度
思路与推导
  1. 高度按边数计算时,高度为 hh 的二叉树最多有 2h+1−12^{h+1}-1 个节点;反解得最小高度为 lceillog2(n+1)ceil−1lceillog_2(n+1) ceil-1。

第 6 题(单选题,2 分)

将十进制小数 100.25 转换为二进制数,结果是( )。

A.
1010100.01
B.
1100100.11
C.
1100100.01
D.
1010100.11

正确答案C

解析详情
答案 C进制转换
思路与推导
  1. 整数部分 100=64+32+4100=64+32+4,二进制为 `1100100`;小数 0.25=2−20.25=2^{-2},二进制为 `.01`,合并得 `1100100.01`。

第 7 题(单选题,2 分)

一个队列从空开始依次执行 `push(2)`、`push(5)`、`pop()`、`push(8)`。此时队首元素是( )。

A.
2
B.
8
C.
5
D.
队列为空

正确答案C

解析详情
答案 C队列
思路与推导
  1. 队列先进先出,弹出的是最早进入的 2,之后队首为 5;再压入 8 不改变队首。

第 8 题(单选题,2 分)

突然断电后,数据不会丢失的存储设备是( )。

A.
内存
B.
缓存
C.
固态硬盘
D.
寄存器

正确答案C

解析详情
答案 C存储器易失性
思路与推导
  1. 固态硬盘使用非易失性闪存,断电后仍能保存数据;内存、缓存和寄存器均为易失性存储。

第 9 题(单选题,2 分)

使用深度优先搜索(DFS)遍历一个 nn 行 mm 列的矩阵。从左上角开始搜索,每次只能向右或向下移动一个位置。在搜索过程中,需要使用一个栈来维护当前搜索路径上的已访问位置。为了确保能够完成整个矩阵的遍历,栈的大小至少为( )。(注:本题不考虑栈空间的大小限制。)

A.
max⁡(n,m)\max(n,m)
B.
m+nm+n
C.
m+n−1m+n-1
D.
n×mn\times m

正确答案C

解析详情
答案 C深度优先搜索栈
思路与推导
  1. 只向右或向下移动时,从左上角到右下角的最长路径包含 n+m−1n+m-1 个位置,因此路径栈至少要能容纳这么多元素。

第 10 题(单选题,2 分)

以下代码的时间复杂度是( )。

int n, i = 1;
cin >> n;
while (i < n) {
    i = i * 3;
}
A.
O(1)O(1)
B.
O(n)O(n)
C.
O(log⁡n)O(\log n)
D.
O(nlog⁡n)O(n\log n)

正确答案C

解析详情
答案 C循环复杂度
思路与推导
  1. 变量 `i` 每轮乘 3,执行约 log3nlog_3 n 次;换底只带来常数因子,所以复杂度为 O(logn)O(log n)。

第 11 题(单选题,2 分)

某城市有 8 个交通枢纽,如果要建设一个完全图式的道路网络,使得任意两个枢纽之间都有直达道路,需要建设( )条道路。

A.
28
B.
64
C.
16
D.
7

正确答案A

解析详情
答案 A完全图
思路与推导
  1. 8 个顶点的无向完全图边数为 inom{8}{2}=8 imes7/2=28。

第 12 题(单选题,2 分)

从 5 个不同的红球和 3 个不同的蓝球中,至少取 1 个球,最多取 4 个球,且红球和蓝球都必须至少取一个,不同的取法有( )种。

A.
120
B.
125
C.
180
D.
210

正确答案B

解析详情
答案 B组合计数
思路与推导
  1. 取 2、3、4 个球且两色非空的方案数分别为 15、45、65,总数为 15+45+65=12515+45+65=125。

第 13 题(单选题,2 分)

一棵二叉搜索树中的关键字互不相同。能够按关键字严格递增顺序访问所有结点的遍历方式是( )。

A.
前序遍历
B.
中序遍历
C.
后序遍历
D.
层序遍历

正确答案B

解析详情
答案 B二叉搜索树
思路与推导
  1. 二叉搜索树满足左子树关键字小于根、右子树关键字大于根,中序遍历按左、根、右访问,因此得到严格递增序列。

第 14 题(单选题,2 分)

一个时间复杂度为 O(n3)O(n^3) 的算法,当 nn 从 100 增大到 200 时,运行时间大约变为原来的( )倍。

A.
2
B.
4
C.
8
D.
16

正确答案C

解析详情
答案 C渐进复杂度
思路与推导
  1. 当输入规模变为 2 倍时,立方复杂度的运行量变为 (2n)3/n3=8(2n)^3/n^3=8 倍。

第 15 题(单选题,2 分)

已知 `bool a=true, b=false, c=true`,表达式 `(!a || b) && c` 的值为( )。

A.
`true`
B.
`false`
C.
1 或 0,无法确定
D.
表达式无法编译

正确答案B

解析详情
答案 B逻辑运算
思路与推导
  1. `!a` 为假,`!a || b` 仍为假;假与 `c` 进行 `&&` 的结果为假,所以选择 `false`。

二、阅读程序(1)

1 | #include <iostream>
2 | using namespace std;
3 | int solve(int x, int y) {
4 |     if (y == 0) return x;
5 |     if (x < y) swap(x, y);
6 |     return solve(y, x - y);
7 | }
8 | int main() {
9 |     int a, b;
10 |     cin >> a >> b;
11 |     int k = solve(a, b);
12 |     cout << a / k << "/" << b / k << endl;
13 |     return 0;
14 | }
15 | // 输入的 a 和 b 是不大于 10000 的正整数

第 16 题(判断题,2 分)

函数 `solve(int x, int y)` 计算 xx 和 yy 的最大公约数。( )

正确答案正确

解析详情
答案 正确最大公约数
思路与推导
  1. 函数通过反复交换并相减,把问题化为更小的一对正整数;当第二个参数为 0 时,第一个参数就是最大公约数。

第 17 题(判断题,2 分)

把第 5 行代码去掉,程序会正常输出,但结果数值可能不对。( )

正确答案错误

解析详情
答案 错误递归终止
思路与推导
  1. 删除交换后,若 `x < y`,下一次会传入负数 `x-y`,递归不能按预期收敛,最终可能栈溢出而无法正常输出。

第 18 题(判断题,2 分)

如果输入的值为 160 和 115,则程序的输出结果为 `23/32`。( )

正确答案错误

解析详情
答案 错误分数约分
思路与推导
  1. gcd(160,115)=5gcd(160,115)=5,程序输出 `160/5` 与 `115/5`,即 `32/23`,不是 `23/32`。

第 19 题(单选题,4 分)

如果输入 1817 和 299,则输出为( )。

A.
1817/299
B.
97/13
C.
79/23
D.
79/13

正确答案D

解析详情
答案 D最大公约数应用
思路与推导
  1. gcd(1817,299)=23gcd(1817,299)=23,约分得到 1817/23=791817/23=79、299/23=13299/23=13,所以输出 `79/13`。

第 20 题(单选题,4 分)

如果输入 x,yx,y 为 1…100001\ldots10000 中随机生成的数,则程序的平均时间复杂度为( )。

A.
O(1)O(1)
B.
O(log⁡n)O(\log n)
C.
O(n)O(n)
D.
O(n2)O(n^2)

正确答案B

解析详情
答案 B平均时间复杂度
思路与推导
  1. 对固定较大参数,辗转相减的平均步数与调和级数同阶;再对随机输入平均后仍为 O(logn)O(log n)。

二、阅读程序(2)

1 | #include <iostream>
2 | using namespace std;
3 | int main() {
4 |     int n, sum = 0;
5 |     cin >> n;
6 |     int arr[100];
7 |     for (int i = 0; i < n; i++) {
8 |         cin >> arr[i];
9 |     }
10 |     for (int i = 0; i < n; i++) {
11 |         int cnt = 0;
12 |         for (int j = 0; j < n; j++) {
13 |             if (arr[j] > arr[i]) {
14 |                 cnt++;
15 |             }
16 |         }
17 |         sum += (cnt == 1) * arr[i];
18 |     }
19 |     cout << sum << endl;
20 |     return 0;
21 | }
22 | // 输入的所有数为绝对值均不大于 1000 的整数

第 21 题(判断题,2 分)

若输入数组为 `[5, 3, 8, 2]`,则程序输出为 5。( )

正确答案正确

解析详情
答案 正确程序执行模拟
思路与推导
  1. 数组中只有 5 恰好有一个比它大的元素 8,因此累加值为 5。

第 22 题(判断题,2 分)

数组中可能存在多个元素满足条件,程序会将它们全部累加。( )

正确答案正确

解析详情
答案 正确重复元素与累加
思路与推导
  1. 循环逐个检查数组位置;若多个元素各自满足 `cnt == 1`,语句会把它们分别加入 `sum`。

第 23 题(判断题,2 分)

如果程序输出为 0,则数组中的所有元素一定都相等。( )

正确答案错误

解析详情
答案 错误反例构造
思路与推导
  1. 输出 0 还可能因为严格次大值本身为 0,或最大值重复导致没有元素满足 `cnt == 1`,并不能推出所有元素相等。

第 24 题(单选题,4 分)

若输入数组为 `[9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -2]`,则输出为( )。

A.
-2
B.
-1
C.
8
D.
9

正确答案C

解析详情
答案 C程序执行模拟
思路与推导
  1. 给定数组严格递减且元素互异,8 恰好只有一个更大的元素 9,因此程序输出 8。

第 25 题(单选题,3 分)

该程序计算的是数组中( )。

A.
第二大元素的值
B.
所有比平均值大的元素之和
C.
所有满足“恰好有一个元素比它大”的元素之和
D.
最大元素和最小元素的和

正确答案C

解析详情
答案 C嵌套循环含义
思路与推导
  1. 对每个 `arr[i]`,内层循环统计严格大于它的元素数;程序累加所有统计值恰好为 1 的元素,所以选 C。

二、阅读程序(3)

1 | #include <iostream>
2 | #include <vector>
3 | #include <algorithm>
4 | using namespace std;
5 |
6 | int n, k, ans = 0;
7 | vector<int> nums;
8 | vector<bool> used;
9 |
10 | void dfs(int pos, int sum, int count) {
11 |     if (count == k) {
12 |         if (sum % 2 == 0) {
13 |             ans++;
14 |         }
15 |         return;
16 |     }
17 |     if (pos >= n) return;
18 |
19 |     if (!used[pos]) {
20 |         used[pos] = true;
21 |         dfs(pos + 1, sum + nums[pos], count + 1);
22 |         used[pos] = false;
23 |     }
24 |
25 |     dfs(pos + 1, sum, count);
26 | }
27 |
28 | int main() {
29 |     cin >> n >> k;
30 |     nums.resize(n);
31 |     used.resize(n, false);
32 |
33 |     for (int i = 0; i < n; i++) {
34 |         cin >> nums[i];
35 |     }
36 |
37 |     dfs(0, 0, 0);
38 |     cout << ans << endl;
39 |     return 0;
40 | }

第 26 题(判断题,2 分)

如果输入数据中存在重复数字,则重复数字的数量不会影响输出结果。( )

正确答案错误

解析详情
答案 错误组合计数
思路与推导
  1. 程序按数组位置选择元素,数值相同的位置仍代表不同选择,因此重复数字的数量会改变方案数。

第 27 题(判断题,2 分)

去掉 `nums.resize(n);` 和 `used.resize(n, false);` 这两行代码,不会影响程序的正常运行。( )

正确答案错误

解析详情
答案 错误vector 容量
思路与推导
  1. 代码通过下标写入 `nums[i]` 和访问 `used[pos]`;删除两次 `resize` 后两个 vector 为空,会发生越界访问。

第 28 题(判断题,2 分)

如果 n=10,k=2n=10,k=2,nn 个数为 1~10 的任意排列,则输出结果是 2C522C_5^2。( )

正确答案正确

解析详情
答案 正确奇偶组合
思路与推导
  1. 1~10 含 5 个奇数和 5 个偶数;两数之和为偶数需同奇偶,方案数为 inom{5}{2}+inom{5}{2}=2inom{5}{2}。

第 29 题(单选题,3 分)

如果输入的 kk 为 0,则程序的输出结果为( )。

A.
0
B.
1
C.
需要结合数组的数值,才能计算结果
D.
以上都不对

正确答案B

解析详情
答案 B递归边界
思路与推导
  1. 当 k=0k=0 时首次调用已满足 `count == k`,且初始和 0 为偶数,因此 `ans` 加 1 后返回,输出 1。

第 30 题(单选题,4 分)

程序的时间复杂度是( )。

A.
O(n)O(n)
B.
O(n2)O(n^2)
C.
O(2n)O(2^n)
D.
O(nk)O(n^k)

正确答案C

解析详情
答案 C回溯复杂度
思路与推导
  1. 每个元素都有选或不选两个分支;在最坏情况下会遍历指数数量的状态,所以时间复杂度为 O(2n)O(2^n)。

三、完善程序(1)计数排序

(计数排序)输入 nn 个取值在 00 到 kk 之间的整数,按从小到大的顺序输出。保证 1≤n≤1051\le n\le10^5,0≤k≤1060\le k\le10^6。

1 | #include <iostream>
2 | #include <vector>
3 | using namespace std;
4 | int main() {
5 |     int n, k;
6 |     cin >> n >> k;
7 |     vector<int> cnt(①, 0);
8 |     for (int i = 0; i < n; ++i) {
9 |         int x;
10 |         cin >> x;
11 |         ②;
12 |     }
13 |     bool first = true;
14 |     for (int v = 0; ③; ++v) {
15 |         while (④) {
16 |             if (!first) cout << ' ';
17 |             cout << v;
18 |             first = false;
19 |             ⑤;
20 |         }
21 |     }
22 |     cout << '\n';
23 |     return 0;
24 | }

第 31 题(单选题,3 分)

① 处应填( )。

A.
k - 1
B.
k
C.
n + 1
D.
k + 1

正确答案D

解析详情
答案 D计数数组大小
思路与推导
  1. 需要使用下标 0 到 k,共 k+1 个位置,所以计数数组长度应为 `k+1`。

第 32 题(单选题,3 分)

② 处应填( )。

A.
++cnt[i]
B.
cnt[x] = 1
C.
++cnt[x]
D.
++x

正确答案C

解析详情
答案 C频次统计
思路与推导
  1. 读入数值 x 后,应把它对应的计数 `cnt[x]` 加 1。

第 33 题(单选题,3 分)

③ 处应填( )。

A.
v < n
B.
v < k
C.
v <= k
D.
v <= n

正确答案C

解析详情
答案 C计数排序枚举范围
思路与推导
  1. 输入值可能等于 k,所以输出阶段必须枚举 `v<=k`。

第 34 题(单选题,3 分)

④ 处应填( )。

A.
cnt[v] > 0
B.
cnt[v] < 0
C.
v < cnt[v]
D.
first

正确答案A

解析详情
答案 A重复输出
思路与推导
  1. 只要值 v 的剩余出现次数仍大于 0,就应继续输出它。

第 35 题(单选题,3 分)

⑤ 处应填( )。

A.
++cnt[v]
B.
--cnt[v]
C.
--v
D.
++n

正确答案B

解析详情
答案 B计数消耗
思路与推导
  1. 每输出一次 v,就应把它的剩余计数减 1,即执行 `--cnt[v]`。

三、完善程序(2)最长波动子序列

波动序列指序列中的元素值交替上升和下降,最长波动子序列是已有的序列中满足这种波动性质的最长子序列。

1 | #include <iostream>
2 | #include <vector>
3 | #include <algorithm>
4 | #define N 1009
5 | using namespace std;
6 | int n;
7 | int dp[N][2];
8 | int main() {
9 |     cin >> n;
10 |     vector<int> nums(n);
11 |     for (int i = 0; i < n; i++) {
12 |         cin >> nums[i];
13 |     }
14 |
15 |     ①
16 |     for (int i = 1; i < n; i++) {
17 |         for (int j = 0; ②; j++) {
18 |             if (③) {
19 |                 int tmp = dp[j][1] + 1;
20 |                 if (tmp > dp[i][0]) {
21 |                     dp[i][0] = tmp;
22 |                 }
23 |             }
24 |             else if (nums[i] < nums[j]) {
25 |                 int tmp = ④;
26 |                 if (tmp > dp[i][1]) {
27 |                     dp[i][1] = tmp;
28 |                 }
29 |             }
30 |         }
31 |     }
32 |
33 |
34 |     int max_Len = 1;
35 |     for (int i = 1; i < n; i++) {
36 |         max_Len = max(max_Len, ⑤);
37 |     }
38 |
39 |     cout << max_Len << endl;
40 |
41 |     return 0;
42 | }

第 36 题(单选题,3 分)

① 处应填( )。

A.
memset(dp, 1, sizeof(dp));
B.
memset(dp, 0x3f, sizeof(dp));
C.
fill(dp, dp + n * 2, 1);
D.
fill(dp[0], dp[0] + n * 2, 1);

正确答案D

解析详情
答案 D二维数组初始化
思路与推导
  1. `dp` 的 2n2n 个连续整数都应初始化为 1,`fill(dp[0], dp[0] + n * 2, 1)` 能完成该操作。

第 37 题(单选题,3 分)

② 处应填( )。

A.
j < n
B.
j <= n
C.
j < i
D.
j <= i

正确答案C

解析详情
答案 C动态规划枚举
思路与推导
  1. 计算第 ii 个位置的状态时,只能从它之前的下标转移,因此应枚举 `j < i`。

第 38 题(单选题,3 分)

③ 处应填( )。

A.
nums[i] > nums[j]
B.
nums[i] >= nums[j]
C.
nums[j] > nums[i]
D.
nums[j] >= nums[i]

正确答案A

解析详情
答案 A波动子序列状态
思路与推导
  1. 后续更新 `dp[i][0]` 使用的是以下降结束的 `dp[j][1]`,因此当前一步必须上升,即 `nums[i] > nums[j]`。

第 39 题(单选题,3 分)

④ 处应填( )。

A.
dp[i][0] + 1
B.
dp[i][1] + 1
C.
dp[j][0] + 1
D.
dp[j][1] + 1

正确答案C

解析详情
答案 C动态规划转移
思路与推导
  1. 当 `nums[i] < nums[j]` 时形成一次下降,应由以前一个位置上升结束的状态转移,故为 `dp[j][0] + 1`。

第 40 题(单选题,3 分)

⑤ 处应填( )。

A.
dp[i][0]
B.
dp[i][1]
C.
max(dp[i][0], dp[i][1])
D.
min(dp[i][0], dp[i][1])

正确答案C

解析详情
答案 C最长波动子序列
思路与推导
  1. 以位置 ii 结尾的最优长度可能最后上升,也可能最后下降,应取 `max(dp[i][0], dp[i][1])`。