试卷解析 · 理解每一步
提高组 CSP-S 2026 初赛模拟卷 5
CSPS-2026-R1-Mock-5
试卷解析总览,可直接查看每题答案与解析。
第 1 题(单选题,2 分)
在 NOI Linux 中,编译成功后,运行可执行文件 main 的命令是()。
正确答案B
解析详情
在 Linux 中,运行当前目录下的可执行文件需要在文件名前加 ./。默认并没有 run、execute、start 这些指令。
第 2 题(单选题,2 分)
计算机能直接识别和执行的语言是()。
正确答案C
解析详情
机器语言是由 0 和 1 组成的二进制代码,是计算机硬件唯一能直接理解和执行的语言。高级语言(如 C++、Python)和汇编语言都需要经过翻译(编译或汇编)转换成机器语言后才能被 CPU 执行。
第 3 题(单选题,2 分)
用 24 位二进制数来表示的 RGB 颜色,将其每位二进制数取反(0 改为 1,1 改为 0),即变为另一种颜色,这种操作称为颜色反相。若某 RGB 颜色值用十六进制表示为 123456H,则其反相后的颜色值用十六进制表示为()。
正确答案C
解析详情
RGB 颜色是 24 位,所以每个颜色分量(红、绿、蓝)各占 8 位。十六进制 123456H 表示红是 12H,绿是 34H,蓝是 56H。在十六进制中,每个两位十六进制数代表一个 8 位的字节。
红: (二进制)取反 ;
绿: (二进制)取反 CBH;
蓝: (二进制)取反 。
所以,反相后的颜色是EDCBA9H。或在十六进制中取反相当于每一位 。
第 4 题(单选题,2 分)
以下代码段的时间复杂度是()。
int i = 2;
while (i <= n) { // 保证 n 不大于 1e9
for (int j = 1; j <= i; j++) {
// O(1) 操作
}
i += i / 2;
}正确答案A
解析详情
i 的增长序列近似于等比数列(约每次乘 1.5),总复杂度是一个公比为 1.5 的等比数列之和,其与最后一项的大小是同一量级,也就是 O(n)。
第 5 题(单选题,2 分)
无向连通图存在欧拉通路的充要条件是()。
正确答案A
解析详情
无向连通图有欧拉通路当且仅当奇度数顶点数为 0 或 2。
第 6 题(单选题,2 分)
x 是 int 变量,表达式 x & -x 的结果是()。
正确答案D
解析详情
这称为 lowbit 操作,原理是利用了补码性质。例如 (实际上 int 有 32 位,此处以 8 位为例足以解释原理), 存为 。
第 7 题(单选题,2 分)
用哈夫曼树处理 n 个权值不同的字符,哈夫曼树的节点总数为()。
正确答案C
解析详情
哈夫曼树是没有一度点的二叉树,有 n 个叶节点的这种二叉树共有 2n-1 个节点,因为每增加一个非叶节点就减少一个连通分支。
第 8 题(单选题,2 分)
执行 int a = 15, b = 6; a = a^b; b = a^b; a = a^b; 后,a 和 b 的值是()。
正确答案A
解析详情
使用异或运算交换变量,避免临时变量。异或按位独立运算,只要对一位进行验证即可。
第 9 题(单选题,2 分)
一个具有 n 个顶点且无重边的二分图,最多有( )条边。
正确答案A
解析详情
左部有 x 个点时,连满边共 条,此式在 x 越接近 n/2 时值越大,当两部分顶点数尽可能相等时边数最多,为 。
第 10 题(单选题,2 分)
后缀表达式 “5 3 + 2 * 4 -” 的值是()。
正确答案A
解析详情
用栈模拟:5+3=8,8×2=16,16-4=12。或画出表达式树转为中缀表达式: 。
第 11 题(单选题,2 分)
下列几种排序算法中,在最坏情况下,( )算法的时间复杂度与其他三种不同。
正确答案B
解析详情
在最坏情况下,快速排序、插入排序和冒泡排序的时间复杂度均为 ,而堆排序为 。
第 12 题(单选题,2 分)
抛掷一枚均匀骰子,直到出现6为止,期望抛掷次数是()。
正确答案C
解析详情
几何分布,成功概率 p = 1/6,期望次数 E = 1/p = 6。或直接用朴素方法,恰好抛 i 次
得 6 的概率为 。期望值为无穷级数: ,用错位技巧, 。相减得 ,则 。
第 13 题(单选题,2 分)
在 的网格中,要从左上角格子内走到右下角,只可以向右、向下、向右下移动,有( )种不同的路径。
正确答案C
解析详情
手算更快(标数法): ,答案是 231。
第 14 题(单选题,2 分)
在单调不降的数组中进行二分查找,目标值可能出现多次,希望找到第一次出现的位置,正确的处理方式是()。
正确答案D
解析详情
在找到目标值后,不终止搜索,而是继续在左半部分查找更早的出现,这样处理效率最高。
第 15 题(单选题,2 分)
将字母 A~F 排成圆环,要求 A 和 B 必须相邻,C 和 D 不能相邻,旋转重合视为排法相同,则共有( )种排法。
正确答案C
解析详情
将 AB 视为一个整体,共有 种(本来是 5!,旋转重合除掉一个 5,乘 2 是 AB 内部换序),排除 C 和 D 也相邻的情况,有 种。
二、阅读程序(1)
#include <bits/stdc++.h>
using namespace std;
const int N = 1009;
int n, a[N], res[2];
void solve() {
int xor_all = 0;
for (int i = 0; i < n; i++) xor_all ^= a[i];
int low_bit = xor_all & -xor_all;
for (int i = 0; i < n; i++) {
if (a[i] & low_bit) res[0] ^= a[i];
else res[1] ^= a[i];
}
}
int main() {
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
solve();
cout << res[0] << " " << res[1] << endl;
return 0;
}第 16 题(判断题,2 分)
程序的输出结果有可能为 0。 ( )
正确答案正确
解析详情
如所有数都出现偶数次则输出 0。
第 17 题(判断题,2 分)
xor_all 是两个单独数值的异或结果。 ( )
正确答案错误
解析详情
xor_all 是所有出现奇数次的数的异或和,但这不一定是两个。
第 18 题(判断题,2 分)
程序的功能是找出数组中最多两个不同的数,这两个数的出现次数是奇数。 ()
正确答案正确
解析详情
见前述整体分析。
第 19 题(判断题,2 分)
low_bit = xor_all & -xor_all 能找到 xor_all 二进制中最低位的 1。
正确答案正确
解析详情
这是位运算的常用技巧。前面的选择题里已有说明。
第 20 题(单选题,2 分)
输入6 1 2 2 3 3 5时,输出为()。
正确答案C
解析详情
两个数 1 和 5 只出现 1 次,根据程序的计算规则,low_bit 取 1 的那个数先输出,所以是 5,1 不是 1,5。
第 21 题(单选题,2 分)
输入72133612时,输出为()。
正确答案D
解析详情
只有 6 出现过 1 次,其他都是成对出现,先输出 6 再输出 0。
二、阅读程序(2)
#include <bits/stdc++.h>
using namespace std;
const int N = 100009;
int n, k, d[N];
int solve(int left, int right, int k) {
if (left == right) return d[left];
int pivot = d[right], i = left - 1;
for (int j = left; j < right; j++)
if (d[j] > pivot) swap(d[++i], d[j]);
swap(d[i + 1], d[right]);
int pivotIndex = i + 1;
if (k == pivotIndex) return d[k];
if (k < pivotIndex) return solve(left, pivotIndex - 1, k);
return solve(pivotIndex + 1, right, k);
}
int main() {
cin >> n >> k;
for (int i = 0; i < n; i++) cin >> d[i];
cout << solve(0, n - 1, k - 1) << endl;
return 0;
}第 22 题(判断题,2 分)
输入731542736时,输出结果是3。()
正确答案错误
解析详情
输出应该是 5,第 3 大的数,而不是第 3 小的数。
第 23 题(判断题,2 分)
程序的功能是实现快速排序。 ()
正确答案错误
解析详情
代码参照快速排序的思路,但实际上并没有排序。
第 24 题(判断题,2 分)
算法在处理过程中,总是将数组分为大于基准值和小于或等于基准值的两部分。 ()
正确答案正确
解析详情
寻找第 k 大的元素,分区时使用 d[j] > pivot 的比较,将大于基准的元素移到左边,小于等于基准的元素留在右边。
第 25 题(判断题,2 分)
如果数组的所有元素都相同,该算法会陷入无限循环。 ()
正确答案错误
解析详情
即使所有元素相同,算法也能正常工作。当所有元素相同时,每次分区基准总是在 right 位置,唯一的问题是复杂度会退化到平方,但不会发生死循环。
第 26 题(单选题,3 分)
输入8315427368时,输出结果是()。
正确答案C
解析详情
第3大的数为6,选C。
第 27 题(单选题,3 分)
该算法在最坏情况下的时间复杂度出现在()时。
正确答案A(另接受:B)
解析详情
当轴点选到最大值/最小值时,分区就会不平衡(一个子数组为空),导致最坏情况下的时间复杂度 。本题选项 B 也是对的,但选项 B 只是选项 A 的一种特殊情况,所以选 A 更合适。
二、阅读程序(3)
#include <bits/stdc++.h>
using namespace std;
int solve(string t1, string t2) {
int m = t1.length(), n = t2.length();
vector<vector<int>> f(m + 1, vector<int>(n + 1, 0));
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (t1[i - 1] == t2[j - 1])
f[i][j] = f[i - 1][j - 1] + 1;
else
f[i][j] = max(f[i - 1][j], f[i][j - 1]);
}
}
return f[m][n];
}
int main() {
string s1, s2;
cin >> s1 >> s2;
cout << solve(s1, s2) << endl;
return 0;
}第 28 题(判断题,2 分)
当两个字符串的长度差异很大时,该算法的时间复杂度会显著增加。 ()
正确答案错误
解析详情
算法的时间复杂度与两个字符串的长度的乘积相关,但与长度差异大小无关。
第 29 题(判断题,2 分)
如果交换两个输入字符串的顺序,程序最终输出的结果有可能不同。 ()
正确答案错误
解析详情
LCS 具有对称性,交换字符串顺序不会改变 LCS 长度,因为公共子序列的定义与顺序无关。
第 30 题(判断题,2 分)
程序的功能是求两个字符串的最长公共子序列的长度。 ()
正确答案正确
解析详情
参见前述整体解析。
第 31 题(判断题,2 分)
输入的两个字符串不为空时,输出的结果也可能为 0。()
正确答案正确
解析详情
不存在任何公共子序列时,输出结果为 0。
第 32 题(单选题,3 分)
输入 ABCDCBABC ACBDCABAC 时,程序的输出结果为()。
正确答案B
解析详情
LCS 为 ACDCABC。
第 33 题(单选题,3 分)
在状态转移方程中,当 text1[i-1] != text2[j-1] 时,dp[i][j] = max(dp[i-1][j], dp[i][j-1]),这体现了()。
正确答案B
解析详情
最优子结构指最优解的子问题也要是最优解,所以还能使用 dp[ ] 的定义,否则子问题最优解之间无法转移,选 B。选项 A,贪心选择肯定不对;选项 C,重叠子问题是 DP 优于暴力枚举的核心性质,任何有效的 DP 理论上都有重叠子问题,但不是这个具体转移方程最典型的体现;选项 D,分治思想狭义上指 divide and conquer,一般分成若干规模相似的子问题再合并,广义上,DP 也可以视为分治思想的应用,即子问题 i,j,拆成最后一步 + 再之前的子问题(i-1,j;i,j-1),再通过转移方程“合并”,但这里这么选比较牵强。选项 B 是最合适的。
三、完善程序(1)
(最短路径变种)在一个 的网格地图中,每个网格单元 都有一个整数高度值 。现在需要从左上角 移动到右下角 ,每次只能向上、下、左、右四个方向移动一个网格单元。但是,移动时相邻两个网格单元的高度差不能超过给定的阈值 。也就是说,从高度为 的格子移动到高度为 的格子时,必须满足 。请设计算法,计算在这种限制条件下从起点到终点的最短路径长度(移动步数)。若无法到达终点,则返回 -1。
#include <bits/stdc++.h>
using namespace std;
const int N = 1009;
int m, n, d;
int h[N][N];
int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
struct Node {
int x, y, dst;
bool operator>(const Node& other) const {
return dst > other.dst;
}
};
int solve() {
vector<vector<int>> dst(m, vector<int>(n, INT_MAX));
dst[0][0] = 0;
priority_queue<Node, vector<Node>, ①> q;
q.push((Node){0, 0, 0});
while (!q.empty()) {
Node now = q.top();
q.pop();
if (②) continue;
for (int i = 0; i < 4; i++) {
int nx = now.x + dx[i];
int ny = now.y + dy[i];
if (nx >= 0 && nx < m && ny >= 0 && ny < n) {
if (③) {
int cost = now.dst + 1;
if (cost < dst[nx][ny]) {
dst[nx][ny] = cost;
④;
}
}
}
}
}
return ⑤;
}第 34 题(单选题,3 分)
① 处应填()。
less<int>less<Node>greater<int>greater<Node>正确答案D
解析详情
要求以 dst 小为 top 的小根堆需要小根堆,根据这里的写法,Node 里重载的是大于,所以声明的时候也传入 greater(不传的话默认用的是 less)。这里 greater 的意思是“以大为小”,priority_queue 默认是大根堆,所以这样变成了小根堆。
第 35 题(单选题,3 分)
②处应填()。
now.dst < dst[now.x] [now.y]now.dst <= dst[now.x] [now.y]now.dst > dst[now.x] [now.y]now.dst >= dst[now.x] [now.y]正确答案D
解析详情
延迟删逻辑。同一位置可能多次进入队列,dst 值不一致,出队时 dst 可能已经被更新,这种情况下,队列中取出的节点对最短路的计算如果没有贡献,需要跳过(不跳过的话逻辑还是对的,但是可能造成复杂度退化)。选 D。
第 36 题(单选题,3 分)
③ 处应填()。
h[now.x] [now.y] - h[nx] [ny] <= dh[nx] [ny] - h[now.x] [now.y] <= dabs(h[now.x] [now.y] - h[nx] [ny]) <= dabs(h[now.x] [now.y] - h[nx] [ny]) > d正确答案C
解析详情
题述约束条件。相邻两个网格单元的高度差不能超过给定的阈值 d。
第 37 题(单选题,3 分)
④处应填()。
q.push((Node){nx, ny});q.push((Node)nx, ny);q.push((Node)(nx, ny, cost));q.push((Node){nx, ny, cost});正确答案D
解析详情
符合要求的几个节点在更新最短路值后进入队列,选 D。选项 C 的语法不对。
第 38 题(单选题,3 分)
⑤ 处应填( )。
(dst[n][m] == INT_MAX ? -1 : dst[n][m]);(dst[n-1][m-1] == INT_MAX ? -1 : dst[n-1][m-1]);(dst[m][n] == INT_MAX ? -1 : dst[m][n]);(dst[m-1][n-1] == INT_MAX ? -1 : dst[m-1][n-1]);正确答案D
解析详情
判断终点的最短路值,终点的格子位置为(m-1, n-1),如果最短路值为初始值 ,则表示走不到,返回 -1,否则返回实际值。选 D。
三、完善程序(2)
(欧拉函数)欧拉函数 是一个在数论中非常重要的函数,它表示小于或等于 n 的正整数中与 n 互素的数的数量。例如, ,因为 1,3,5,7 均与 8 互素。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll eulerPhi(int n) {
if (n == 1) return 1;
vector<int> prime;
int temp = n;
for (int i = 2; i * i <= temp; i++) {
if (temp % i == 0) {
prime.push_back(i);
while (temp % i == 0) temp /= i;
}
}
if (temp > 1) ①;
int k = prime.size();
ll result = 0;
for (int mask = 0; mask < (1 << k); mask++) {
ll product = 1;
int cnt = 0;
for (int i = 0; i < k; i++) {
if (②) {
cnt++;
product *= prime[i];
}
}
if (cnt == 0) {
③;
} else if (cnt % 2 == 1) {
④;
} else {
⑤;
}
}
return result;
}
int main() {
int n;
cin >> n;
cout << eulerPhi(n) << endl;
return 0;
}第 39 题(单选题,3 分)
①处应填()。
prime.add(i);prime.push_back(i);prime.add(temp);prime.push_back(temp);正确答案D
解析详情
此处是对 n 进行素因数分解,并将所有素因数存储在 prime 列表中。因为大于 的素因数至多有一个,循环到 即可。最后如果剩余的数仍非 1,该数就是最后那个最大的素因数。push_back() 是 vector 的语法。
第 40 题(单选题,3 分)
②处应填( )。
mask & imask | (1 << i)mask & (1 << i)mask >> i正确答案C
解析详情
mask 是一个压缩存储技巧,实际上枚举的是 {1..k} 的子集,表示 k 个素因数中选哪些(mask 二进制位是 1 就表示选这个素数)。位运算 mask & (1 << i) 用来检查 mask 的第 i 位是否为 1,如果是,则表示该素因数在子集中,product 是选中素因数子集的乘积。
第 41 题(单选题,3 分)
③处应填( )。
result *= n;result += n;result -= n;result /= 0;正确答案B
解析详情
cnt=0 对应空集,在容斥原理中空集表示不考虑任何约束条件,应该加上所有 n 个数,表示全集。
第 42 题(单选题,3 分)
④处应填( )。
result += n / product;result -= n / product;result = n / product;result *= n / product;正确答案B
解析详情
当子集大小为奇数时,应该减去这些素因数的公倍数(与 n 不互素),共 n/product 个。选 B。
第 43 题(单选题,3 分)
⑤处应填( )。
result += n / product;result -= n / product;result = n / product;result *= n / product;正确答案A
解析详情
同理。