一、单项选择题
(共 15 题,每题 2 分,共计 30 分;每题有且仅有一个正确选项)
试卷解析 · 理解每一步
CSPJ-2026-R1-Mock-AI-1
试卷解析总览,可直接查看每题答案与解析。
(共 15 题,每题 2 分,共计 30 分;每题有且仅有一个正确选项)
在 Linux 终端执行命令 `g++ main.cpp -o app`,若编译成功,通常会得到( )。
正确答案B
`-o app` 指定输出文件名为 `app`;编译成功后生成该可执行文件,但不会自动运行。
若一个 `unsigned char` 恰好占 8 个二进制位,则它能表示的整数范围是( )。
正确答案D
8 位无符号整数共有 种状态,因此取值为 到 。
执行下列程序后,输出结果是( )。
void change(int &x, int y) {
x += y;
y *= 2;
}
int a = 3, b = 4;
change(a, b);
cout << a << " " << b;正确答案A
`x` 是引用,执行 `x += y` 后 `a` 变为 7;`y` 是值传递,修改副本不会影响 `b`,故输出 `7 4`。
执行下列代码后,字符串 `s` 的值是( )。
string s = "cspj";
s.erase(1, 2);
s.insert(1, "++");正确答案C
`erase(1, 2)` 删除下标 1 开始的 `sp`,得到 `cj`;再在下标 1 插入 `++`,得到 `c++j`。
十进制整数 42 的二进制表示为 `101010`。表达式 `42 ^ (1 << 3)` 的值是( )。
正确答案D
`1 << 3` 等于 8,42 的第 3 位为 1;与 8 异或会把该位翻转为 0,所以结果为 。
二进制数 与八进制数 之和,用十六进制表示为( )。
正确答案C
,,两者之和为 68,即十六进制的 。
一棵完全二叉树共有 2026 个结点,则其叶结点数为( )。
正确答案B
顺序编号为 1 到 2026 时,编号不超过 的结点有孩子,因此叶结点数为 。
一棵二叉树的前序遍历为 `A B D E C F G`,中序遍历为 `D B E A F C G`,则其后序遍历为( )。
正确答案A
前序首元素确定根为 A,中序将左右子树划分为 `D B E` 和 `F C G`;分别还原后,后序为 `D E B F G C A`。
元素 `1,2,3,4,5` 按此顺序依次入栈,入栈和出栈操作可以交错进行。下列不可能得到的出栈序列是( )。
正确答案C
要先输出 3,栈中必然已有 `1,2,3`;弹出 3 后栈顶是 2,不可能越过 2 先输出 1,因此 `3,1,2,5,4` 不合法。
下面哪一个序列可以作为一个有 5 个顶点的简单无向连通图的度数序列?( )
正确答案B
可由一个 5 阶环再增加一条弦得到,且图保持连通;其余选项度数和为奇数或含孤立点。
在下列排序算法的常见实现中,通常不具有稳定性的是( )。
正确答案D
选择排序交换最小元素与当前位置时,可能跨过相等元素并改变其相对次序,因此常见实现不稳定。
长度为 8 的二进制串中,不包含两个连续的 `1` 的串共有( )个。
正确答案A
设长度为 的合法串数为 。末位为 0 时有 种,末位为 1 时前一位必须为 0,有 种;由 得 。
函数 `f` 定义如下,则 `f(5)` 的返回值是( )。
int f(int n) {
if (n <= 1) return n + 1;
return f(n - 1) + f(n - 2);
}正确答案A
由边界得到 ,之后依次为 3、5、8、13,所以 `f(5)` 返回 13。
数组 `a[1..n]` 的前缀和定义为 ,。区间 等于( )。
正确答案B
`p[r]` 包含前 项,减去前 项后,恰好留下下标 到 的元素和。
设 为正的 2 的整数次幂,且下列程序不会发生整数溢出。其时间复杂度为( )。
long long cnt = 0;
for (int i = 1; i <= n; i *= 2)
for (int j = 0; j < i; ++j)
++cnt;正确答案C
内层执行次数依次为 ,总次数小于 ,因此时间复杂度为 。
假设输入字符串只包含小写英文字母,且长度为 。判断题正确填 ✓,错误填 ✗。
1 | #include <iostream>
2 | #include <string>
3 | using namespace std;
4 | string reduce_string(const string &s) {
5 | string t;
6 | for (char c : s) {
7 | if (!t.empty() && t.back() == c)
8 | t.pop_back();
9 | else
10 | t.push_back(c);
11 | }
12 | return t;
13 | }
14 | int main() {
15 | string s;
16 | cin >> s;
17 | string t = reduce_string(s);
18 | cout << t << '\n';
19 | cout << t.size() << '\n';
20 | }输出字符串长度的奇偶性一定与输入字符串长度的奇偶性相同。
正确答案正确
每读入一个字符,`t` 的长度只会增加 1 或减少 1,因此奇偶性每次翻转;处理 个字符后长度与 同奇偶。
若输入为 `abca`,则第一行输出为空行。
正确答案错误
输入 `abca` 时相邻字符始终不同,四个字符都会依次压入 `t`,第一行输出 `abca`。
函数返回的字符串中一定不存在两个相邻且相同的字符。
正确答案正确
压入字符前要求它与当前末尾不同;弹出只会删除末尾。因此处理过程中以及最终结果中都不会出现相邻相同字符。
若将第 8 行的 `t.pop_back()` 改为 `t.clear()`,程序对任意输入的输出都不变。
正确答案错误
输入 `abbc` 时原程序得到 `ac`;若改为 `clear()`,处理两个 `b` 后会清空整个 `t`,最终得到 `c`,输出发生变化。
若输入为 `abbaca`,则第一行输出为( )。
正确答案B
依次处理 `abbaca`:两个 `b` 抵消,随后两个 `a` 抵消,剩余字符依次为 `c`、`a`,第一行输出 `ca`。
该程序的时间复杂度和额外空间复杂度分别为( )。
正确答案D
每个输入字符只进行一次判断和一次压入或弹出,时间为 ;最坏情况下 `t` 保存全部字符,额外空间为 。
输入保证 、,并且数组中的所有元素均为正整数。判断题正确填 ✓,错误填 ✗。
1 | #include <iostream>
2 | #include <vector>
3 | using namespace std;
4 | int main() {
5 | int n;
6 | long long k;
7 | cin >> n >> k;
8 | vector<long long> a(n);
9 | for (int i = 0; i < n; ++i) cin >> a[i];
10 | long long ans = 0, sum = 0;
11 | int left = 0;
12 | for (int right = 0; right < n; ++right) {
13 | sum += a[right];
14 | while (left <= right && sum > k) {
15 | sum -= a[left];
16 | ++left;
17 | }
18 | ans += right - left + 1;
19 | }
20 | cout << ans << '\n';
21 | return 0;
22 | }每次执行完第 14~17 行的 `while` 循环后,都有 `sum <= k`。
正确答案正确
数组元素均为正数,窗口和超出 时不断移动左端点;循环停止时窗口为空或其元素和已经不超过 。
将第 14 行的 `while` 改为 `if`,程序对所有合法输入的输出都不变。
正确答案错误
例如 、数组为 `1 1 3`。加入 3 后窗口和为 5,只删除一个 1 仍为 4,必须继续删除,因此不能把 `while` 改成 `if`。
程序输出的是数组中元素和不超过 的连续非空子数组个数。
正确答案正确
固定右端点后,`left` 是最靠左的合法起点;以 `right` 结尾的合法非空子数组共有 `right-left+1` 个,累加后得到全部答案。
由于程序中存在两层循环,因此最坏时间复杂度是 。
正确答案错误
虽然 `while` 位于 `for` 内,但 `left` 在整个程序中最多从 0 增加到 ,两个指针的总移动次数均为 。
若输入如下,则程序输出为( )。
5 5
1 2 1 3 2正确答案C
五个右端点分别新增 1、2、3、2、2 个合法子数组,累计为 。
对于固定的 ,程序输出的最大可能值是( )。
正确答案A
当 足够大时所有连续非空子数组都合法。长度为 的数组共有 n+(n-1)+cdots+1=rac{n(n+1)}{2} 个连续非空子数组。
输入保证 ,且 均为非负整数。判断题正确填 ✓,错误填 ✗。
1 | #include <algorithm>
2 | #include <iostream>
3 | #include <vector>
4 | using namespace std;
5 | int main() {
6 | int n;
7 | cin >> n;
8 | vector<long long> a(n + 1), dp(n + 1, 0);
9 | for (int i = 1; i <= n; ++i) cin >> a[i];
10 | dp[1] = a[1];
11 | for (int i = 2; i <= n; ++i)
12 | dp[i] = max(dp[i - 1], dp[i - 2] + a[i]);
13 | cout << dp[n] << '\n';
14 | return 0;
15 | }`dp[i]` 表示从前 个数中选择若干个互不相邻的数时,能够得到的最大元素和。
正确答案正确
最优方案要么不选第 个数,价值为 `dp[i-1]`;要么选它并跳过第 个数,价值为 `dp[i-2]+a[i]`,两者取最大。
对于任意 ,都有 `dp[i] <= dp[i + 1]`。
正确答案正确
递推式显式取 `max(dp[i-1], ...)`,所以 `dp[i]` 不会小于 `dp[i-1]`。
将第 12 行改为 `dp[i] = dp[i - 2] + a[i]`,程序对所有合法输入的输出都不变。
正确答案错误
若只保留 `dp[i-2]+a[i]`,就强制选择第 个数。输入 `2` 和 `5 1` 时会把正确答案 5 算成 1。
该程序的时间复杂度为 。
正确答案错误
程序只有一次读入循环和一次从 2 到 的递推循环,每轮为常数操作,因此时间复杂度是 。
若输入如下,则程序输出为( )。
6
4 2 7 3 6 1正确答案D
`dp[1..6]` 依次为 `4,4,11,11,17,17`,对应可选择 4、7、6,最大和为 17。
若所有 都等于 1,则程序输出为( )。
正确答案B
所有权值都是 1 时,只需选择尽可能多的不相邻位置,最多可取第 1、3、5……个位置,共 个。
给定一个 的迷宫,字符 `.` 表示可以通过,字符 `#` 表示障碍。起点和终点坐标均从 0 开始编号,且保证起点、终点不是障碍。每次可以向上、下、左、右移动一格。程序输出从起点到终点的最少移动次数;若无法到达则输出 `-1`。
1 | #include <iostream>
2 | #include <queue>
3 | #include <string>
4 | #include <utility>
5 | #include <vector>
6 | using namespace std;
7 | int main() {
8 | int n, m, sx, sy, tx, ty;
9 | cin >> n >> m;
10 | vector<string> g(n);
11 | for (int i = 0; i < n; ++i) cin >> g[i];
12 | cin >> sx >> sy >> tx >> ty;
13 | vector<vector<int>> dist(n, vector<int>(m, -1));
14 | queue<pair<int, int>> q;
15 | ① = 0;
16 | q.push(②);
17 | int dx[4] = {-1, 1, 0, 0};
18 | int dy[4] = {0, 0, -1, 1};
19 | while (!q.empty()) {
20 | pair<int, int> cur = q.front();
21 | int x = cur.first, y = cur.second;
22 | ③;
23 | for (int d = 0; d < 4; ++d) {
24 | int nx = x + dx[d], ny = y + dy[d];
25 | if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
26 | if (④) {
27 | dist[nx][ny] = ⑤;
28 | q.push(make_pair(nx, ny));
29 | }
30 | }
31 | }
32 | cout << dist[tx][ty] << '\n';
33 | return 0;
34 | }① 处应填( )。
dist[tx][ty]dist[0][0]dist[sx][sy]dist[sy][sx]正确答案C
最短路从起点开始,起点到自身的距离为 0,因此应设置 `dist[sx][sy] = 0`。
② 处应填( )。
make_pair(sx, sy)make_pair(tx, ty)make_pair(0, 0)make_pair(sy, sx)正确答案A
队列中首先应放入起点坐标 `make_pair(sx, sy)`,搜索才能从起点向四周扩展。
③ 处应填( )。
q.push(cur)q.front()q.back()q.pop()正确答案D
读取 `q.front()` 后必须执行 `q.pop()` 删除当前结点,否则它会被反复处理,循环无法正常推进。
④ 处应填( )。
g[nx][ny] == '#' && dist[nx][ny] == -1g[nx][ny] != '#' && dist[nx][ny] == -1g[nx][ny] != '#' && dist[nx][ny] != -1g[nx][ny] == '#' || dist[nx][ny] == -1正确答案B
相邻格既要不是障碍 `#`,又要尚未访问,即 `dist[nx][ny] == -1`,满足两者时才能入队。
⑤ 处应填( )。
dist[nx][ny] + 1dist[sx][sy] + 1dist[x][y] + 1dist[x][y] - 1正确答案C
从当前格移动一步到相邻格,因此新格距离应为 `dist[x][y] + 1`。
给定 和 ,其中 。程序先预处理不超过 的所有素数,然后回答 次询问。每次给出 ,输出区间 内素数的个数。
1 | #include <iostream>
2 | #include <vector>
3 | using namespace std;
4 | int main() {
5 | int n, q;
6 | cin >> n >> q;
7 | vector<bool> is_prime(n + 1, true);
8 | is_prime[0] = is_prime[1] = false;
9 | for (int i = 2; ①; ++i)
10 | if (is_prime[i])
11 | for (int j = ②; j <= n; j += i)
12 | is_prime[j] = ③;
13 | vector<int> pre(n + 1, 0);
14 | for (int i = 1; i <= n; ++i)
15 | pre[i] = ④;
16 | while (q--) {
17 | int l, r;
18 | cin >> l >> r;
19 | cout << ⑤ << '\n';
20 | }
21 | return 0;
22 | }① 处应填( )。
i * i <= ni <= ni < n / 2i * 2 <= n正确答案A
每个合数至少有一个不超过其平方根的质因数,所以只需枚举到 `i * i <= n`。
② 处应填( )。
2 * ii + 1i * in / i正确答案C
当处理质数 时,小于 的倍数已经被更小的质因数筛过,因此从 `i * i` 开始即可。
③ 处应填( )。
truefalseji正确答案B
`j` 是质数 的倍数且不小于 ,一定是合数,所以应令 `is_prime[j] = false`。
④ 处应填( )。
pre[i] + is_prime[i]pre[i - 1] + ipre[i - 1] + is_prime[i - 1]pre[i - 1] + (is_prime[i] ? 1 : 0)正确答案D
`pre[i]` 应等于前 个数中的素数个数,再加上 自身是否为素数,即 `pre[i-1] + (is_prime[i] ? 1 : 0)`。
⑤ 处应填( )。
pre[r] - pre[l - 1]pre[r] - pre[l]pre[r - 1] - pre[l - 1]pre[r] + pre[l - 1]正确答案A
`pre[r]` 统计 1 到 的素数个数,减去 1 到 的个数后,得到闭区间 的答案。