一、单项选择题
(共 15 题,每题 2 分,共计 30 分;每题有且仅有一个正确选项)
CSPJ-2026-R1-Mock-2
试卷解析总览,可直接查看每题答案与解析。
(共 15 题,每题 2 分,共计 30 分;每题有且仅有一个正确选项)
文件型病毒传染的主要对象是( )。
正确答案C
【答案】C
【考点】文件型病毒
【解析】 文件型病毒把病毒代码附着在可执行文件中,运行被感染文件时传播。EXE、COM 只是可执行文件的具体类型,概括对象应选可执行文件。
【易错点】 不要把具体扩展名误当成完整类别。
24 针打印机的分辨率约为 180 dpi。dpi 数越大,打印精度越高。其中单位 dpi 是指( )。
正确答案C
【答案】C
【考点】打印分辨率
【解析】 dpi 是 dots per inch 的缩写,表示每英寸包含的印点数;数值越大,单位长度上的点越密,打印精度通常越高。
【易错点】 inch 是英寸,不是厘米或毫米。
内存地址最重要的特点是( )。
正确答案B
【答案】B
【考点】内存编址
【解析】 内存的每个可寻址单元都必须有唯一地址,处理器才能准确读写目标位置;连续性会因分页等机制而变化,不是最根本属性。
【易错点】 不要把常见的地址递增排列误认为地址最重要的属性。
多媒体计算机是指( )。
正确答案D(另接受:C)
【答案】D
【考点】多媒体计算机
【解析】 按本卷给定答案,多媒体计算机强调借助文字、图像、声音、视频等多种媒体进行综合操作,选择 D;仅有多种功能或多种外设并不能说明具备多媒体能力。
【易错点】 题面 C、D 表述接近,本题应以原卷答案 D 为准。
最早的计算机的用途是( )。
正确答案A
【答案】A
【考点】计算机发展史
【解析】 早期电子计算机首先服务于弹道计算等大规模数值运算,因此最早的主要用途是科学计算。自动控制、仿真和辅助设计是后来逐步扩展的应用。
【易错点】 不要用现代计算机的常见用途反推第一代计算机。
CPU 中( )相当于运算器中的一个存储单元,它的存取速度比存储器快得多。
正确答案D
【答案】D
【考点】CPU 组成
【解析】 寄存器位于 CPU 内部,用来暂存参与运算的数据、地址和状态,访问速度远高于主存和辅存,因此相当于运算器中的高速存储单元。
【易错点】 主存属于内存系统,不是运算器内部的存储单元。
计算机软件一般指的是( )。
正确答案A
【答案】A
【考点】软件分类
【解析】 计算机软件通常分为系统软件和应用软件两大类。操作系统、编译程序等属于系统软件,面向具体任务的软件属于应用软件。
【易错点】 自由软件是按许可方式分类,不能与应用软件并列覆盖全部软件。
操作系统在( )计算机中普遍开始应用。
正确答案C
【答案】C
【考点】计算机代际
【解析】 第三代计算机采用集成电路,硬件能力显著提升,多道程序、分时等操作系统技术得到普遍应用。前两代的操作系统仍处于萌芽或早期阶段。
【易错点】 “开始出现”和“普遍应用”不是同一时间点。
计算机中的数有浮点与定点两种,其中用浮点表示的数通常由( )组成。
正确答案C
【答案】C
【考点】浮点数表示
【解析】 浮点数类似科学记数法,由表示有效数字的尾数和表示缩放次数的阶码组成,数值可写成尾数乘以基数的阶码次幂。
【易错点】 基数通常由格式约定,不是每个浮点数单独存储的两部分之一。
假设用一字节来表示整数,最高位用作符号位,其他位表示数值。例如,00000001 表示 +1,10000001 表示 -1。采用这种表示法的整数 的范围应该是( )。
正确答案A
【答案】A
【考点】原码表示范围
【解析】 最高位只表示符号,其余 7 位表示绝对值,最大绝对值为 ,所以可表示的整数范围是 到 。
【易错点】 题目使用的是符号位加数值位,不是补码,不能套用 到 。
下列叙述中,正确的是( )。
正确答案D
【答案】D
【考点】线性结构
【解析】 二维数组可看成元素本身又是线性表的线性表。队列是先进先出,栈是后进先出;顺序表和链表各有优缺点,不能笼统判定前者更优。
【易错点】 要准确区分栈和队列的出入顺序。
用某种排序方法对线性表 25, 84, 21, 47, 15, 27, 68, 35, 20 进行排序,节点变化如下:
(1) 25, 84, 21, 47, 15, 27, 68, 35, 20;
(2) 20, 15, 21, 25, 47, 27, 68, 35, 84;
(3) 15, 20, 21, 25, 35, 27, 47, 68, 84;
(4) 15, 20, 21, 25, 27, 35, 47, 68, 84。那么,排序方法是( )。
正确答案D
【答案】D
【考点】快速排序
【解析】 第一次变化后,枢轴 25 已就位,左侧元素不大于 25、右侧元素不小于 25;后续又分别对子区间做同样划分,符合快速排序的分区过程。
【易错点】 不要只看最终有序结果,要观察每一趟是否体现枢轴分区。
如果某二叉树的前序遍历序列为 STUWV,中序遍历序列为 UWTVS,那么该二叉树的后序遍历序列是( )。
正确答案A
【答案】A
【考点】二叉树遍历
【解析】 前序首节点 S 是根,中序中 S 左侧全为左子树;左子树根为 T,其左子树由 U、W 构成,右子树为 V。按左、右、根得到后序 WUVTS。
【易错点】 每次划分子树时都要同时使用前序的根和中序的位置。
下列关于数据结构的叙述中,正确的是( )。
正确答案D
【答案】D
【考点】树的孩子兄弟表示法
【解析】 树转换为二叉树时,左指针指向第一个孩子,右指针指向下一个兄弟。根节点没有兄弟,因此转换后的根节点没有右子树。
【易错点】 二叉排序树退化成链时最大检索长度可达 ,不是 。
表达式 的后缀表达式为( )。
正确答案C
【答案】C
【考点】中缀转后缀
【解析】 先把 写成 `1 34 +`,再与 5 相乘得到 `1 34 + 5 *`; 写成 `56 7 /`,最后执行减法,得到 `1 34 + 5 * 56 7 / -`。
【易错点】 后缀表达式中的运算符应放在对应两个操作数之后。
程序输入不超过数组或字符串定义的范围;判断题正确填 ✓,错误填 ✗;除特殊说明外,判断题每题 2 分,选择题每题 3 分。
1 | #include <iostream>
2 | using namespace std;
3 | void hanoi(int n, char a, char b, char c) {
4 | if (n == 1)
5 | cout << n << "_" << a << "_" << c << endl;
6 | else {
7 | hanoi(n - 1, a, c, b);
8 | cout << n << "_" << a << "_" << c << endl;
9 | hanoi(n - 1, b, a, c);
10 | }
11 | }
12 | int main() {
13 | int n;
14 | cin >> n;
15 | hanoi(n, 'A', 'B', 'C');
16 | return 0;
17 | }当 时,程序不会出现死循环。
正确答案错误
【答案】错误
【考点】递归终止条件
【解析】 当 时不满足 `n == 1`,程序会递归调用 `hanoi(-1, ...)`,之后参数继续减小,无法到达终止条件。
【易错点】 不能只检查正数输入,题目范围明确包含 0。
输出共有 行。
正确答案错误
【答案】错误
【考点】递归计数
【解析】 设输出行数为 ,则 且 ,解得 ,并非 。
【易错点】 不要漏掉两次递归之间当前层自身输出的一行。
当 时,将第 4 行的 `==` 改为 `<=`,程序输出结果必定不变。
正确答案正确
【答案】正确
【考点】递归边界
【解析】 在 的前提下,递归参数从 逐级减到 1,不会出现 0 或负数,因此把 `n == 1` 改成 `n <= 1` 仍在同一层终止,输出不变。
【易错点】 结论依赖题设的 条件。
将第 5 行的 `n` 改为 `1`,程序输出结果必定不变。
正确答案正确
【答案】正确
【考点】递归终止分支
【解析】 第 5 行只在 n == 1 的分支中执行,因此执行到这一行时 n 必然等于 1。把这里输出的 n 改成常量 1 不会改变任何输出。
【易错点】 第 8 行也有输出语句,但题目只修改第 5 行。
此程序的时间复杂度是( )。
正确答案D
【答案】D
【考点】递归时间复杂度
【解析】 每个规模为 的调用产生两个规模为 的调用,并做常数次输出,递推式为 ,所以时间复杂度为 。
【易错点】 递归深度是 ,但递归调用总数是指数级。
若要求输出不超过 15 行,则下列 值中( )是合法的。
正确答案B
【答案】B
【考点】汉诺塔输出次数
【解析】 正整数 时输出 行。 恰好输出 15 行; 均超过 15,而 会因缺少终止条件无限递归。
【易错点】 不能把 当作输出 0 行。
1 | #include <cstdio>
2 | #define N 1005
3 | using namespace std;
4 | int num[N];
5 | int main() {
6 | int a1 = 1, n, x;
7 | scanf("%d", &n);
8 | num[1] = 1;
9 | for (int i = 1; i <= n; ++i) {
10 | x = 0;
11 | for (int j = 1; j <= a1; ++j) {
12 | num[j] = num[j] * 5 + x;
13 | x = num[j] / 10;
14 | num[j] %= 10;
15 | }
16 | if (x > 0) num[++a1] = x;
17 | }
18 | printf("0.");
19 | for (int i = a1; i < n; ++i) putchar('0');
20 | for (int i = a1; i >= 1; i--) printf("%d", num[i]);
21 | putchar('\n');
22 | return 0;
23 | }程序输出的是 的值。
正确答案正确
【答案】正确
【考点】高精度小数
【解析】 数组保存 的十进制数字,程序在前面输出 0. 并补足到 位小数,因此整体数值为 。
【易错点】 要把数组内容和最终的小数点位置结合起来判断。
程序执行到倒数第 3 行时,`i` 的值为 1。
正确答案错误(另接受:正确)
【答案】错误
【考点】C++ 变量作用域
【解析】 倒数第 3 行是 `putchar('\n')`。上一行 `for` 中的 `i` 声明在循环头内,循环结束后已经离开作用域,不能说此时 `i` 的值为 1。
【易错点】 循环变量的作用域只覆盖对应的 `for` 语句。
程序结束前,对于任意 ,都有 。
正确答案正确(另接受:错误)
【答案】正确
【考点】高精度乘法
【解析】 每次计算后先用 `/ 10` 取进位,再用 `% 10` 保留当前十进制位;最高进位也只会成为新的数字位,因此 `num[1..a1]` 始终在 0 到 9 之间。
【易错点】 赋值乘积后还会立即执行取模,不能用取模前的临时值判断。
程序输出的是一个小数,且小数末尾可能有多余的 0。
正确答案错误
【答案】错误
【考点】有限小数表示
【解析】 程序输出 的恰好 位小数。 不含因子 2,十进制末位为 5,不会产生多余的末尾 0。
【易错点】 前导补零用于保证小数位数,不是末尾多余零。
此程序的时间复杂度是( )。
正确答案B
【答案】B
【考点】高精度算法复杂度
【解析】 外层循环执行 次,第 次需要处理 的全部十进制位,其位数与 成正比;总工作量为 。
【易错点】 内层上界 `a1` 会随幂次增长,不是固定常数。
若 ,则输出为( )。
正确答案B
【答案】B
【考点】程序模拟
【解析】 时数组得到 ,程序在其前面输出 `0.`,且总共保留 3 位小数,所以最终输出 `0.125`。
【易错点】 数组保存 125,但程序输出的不是整数 125。
1 | #include <iostream>
2 | using namespace std;
3 | int l, n, m, a[50005], ans;
4 | bool check(int dis) {
5 | int count = 0, last = 0;
6 | for (int i = 1; i <= n + 1; i++)
7 | if (a[i] - last < dis) count++;
8 | else last = a[i];
9 | if (count > m) return 0;
10 | return 1;
11 | }
12 |
13 | int main() {
14 | // 输入保证 l, n, m, a[i] 是正整数,且 a[i] 严格递增
15 | cin >> l >> n >> m;
16 | for (int i = 1; i <= n; i++) cin >> a[i];
17 | a[n + 1] = l;
18 | int fl = 0, fr = l;
19 | while (fl <= fr) {
20 | int mid = (fl + fr) / 2;
21 | if (check(mid)) fl = mid + 1, ans = mid;
22 | else fr = mid - 1;
23 | }
24 | cout << ans << endl;
25 | return 0;
26 | }将 `main()` 函数中 `while` 之前的 `fl = 0` 改为 `fl = 1`,程序输出结果必定不变。
正确答案正确
【答案】正确
【考点】二分答案边界
【解析】 位置均为严格递增的正整数,合法方案的最小距离至少为 1,因此距离 0 无需成为最终答案;把二分下界从 0 改为 1 不影响最大可行距离。
【易错点】 该结论依赖题设的正整数和严格递增条件。
程序结束前,必有 `fl > fr`。
正确答案正确
【答案】正确
【考点】二分循环不变量
【解析】 循环条件是 `fl <= fr`,每轮都会令 `fl = mid + 1` 或 `fr = mid - 1`。循环结束的唯一条件就是 `fl > fr`。
【易错点】 结束时左右边界会交错,不一定相等。
若主函数中执行 `check(mid)` 返回 1,则最终的 `ans` 小于或等于此时的 `mid`。
正确答案错误
【答案】错误
【考点】二分答案单调性
【解析】 当 `check(mid)` 返回 1 时,程序立即令 `ans = mid`,之后还会向更大的距离继续搜索,所以最终 `ans` 必定大于等于该 `mid`,而不是小于等于。
【易错点】 可行时更新的是二分下界,不是上界。
此程序的时间复杂度是( )。
正确答案C
【答案】C
【考点】二分答案复杂度
【解析】 `check` 顺序扫描 个位置,耗时 ;二分区间为 ,执行 次,因此总复杂度为 。
【易错点】 对数因子来自答案范围 ,不是石头数量 。
若输入如下,则输出为( )。
25 5 2
2 11 14 17 21正确答案B
【答案】B
【考点】贪心判定与二分答案
【解析】 距离 4 时可移除位置 2 和 14,保留 0、11、17、21、25,相邻距离均不少于 4。距离 5 时贪心至少需移除 2、14、21 三块石头,超过 ,故答案为 4。
【易错点】 终点 25 也必须参与相邻距离检查。
Dijkstra 算法是由荷兰计算机科学家 Dijkstra 于 1959 年提出的,是从图中一个顶点到其余各顶点的最短路径算法,解决的是有向图中的最短路径问题。Dijkstra 算法的主要特点是以源点为中心向外扩展,直到扩展到终点为止。
1 | #include <iostream>
2 | using namespace std;
3 | int main() {
4 | int edgs;
5 | int points;
6 | int dis[10];
7 | int flag[10];
8 | int infinity = 9999999;
9 | cin >> points >> edgs;
10 | int edg[10][10];
11 | for (int i = 1; i <= points; i++) {
12 | for (int j = 1; j <= points; j++) {
13 | if (i == j) {
14 | edg[i][j] = ①;
15 | } else {
16 | edg[i][j] = ②;
17 | }
18 | }
19 | }
20 | int point1, point2, quanzhi;
21 | for (int i = 1; i <= edgs; i++) {
22 | cin >> point1 >> point2 >> quanzhi;
23 | edg[point1][point2] = ③;
24 | }
25 | for (int i = 1; i <= points; i++) dis[i] = edg[1][i];
26 | for (int i = 1; i <= points; i++) flag[i] = 0;
27 | flag[1] = 1;
28 | int min, u;
29 | for (int i = 1; i <= points - 1; i++) {
30 | // 源点到源点不用比较,因此总的次数少一次
31 | min = infinity;
32 | for (int j = 1; j < points; j++) {
33 | if (flag[j] == 0 && dis[j] < min) {
34 | // 核心思想:依次比较出离源点最近的点
35 | min = ④;
36 | u = j;
37 | }
38 | }
39 | flag[u] = 1;
40 | for (int v = 1; v <= points; v++) {
41 | // 找出离源点最近的点后,更新 dis 里面的源点到各个点的值是否最小
42 | if (edg[u][v] < infinity) {
43 | if (dis[v] > dis[u] + edg[u][v]) {
44 | dis[v] = ⑤;
45 | }
46 | }
47 | }
48 | }
49 | for (int i = 1; i <= points; i++) cout << dis[i] << " ";
50 | cout << endl;
51 | return 0;
52 | }① 处应填( )。
infinitydis[i]01正确答案C
【答案】C
【考点】邻接矩阵初始化
【解析】 顶点到自身的最短距离应为 0,因此邻接矩阵对角线 `edg[i][i]` 初始化为 0。
【易错点】 无穷大用于表示不同顶点之间尚无已知边。
② 处应填( )。
infinitydis[i]01正确答案A
【答案】A
【考点】邻接矩阵初始化
【解析】 对于 $i e j$ 且尚未读入边的顶点对,应初始化为 `infinity`,表示当前不可直接到达。
【易错点】 若初始化为 0,会被误认为存在权值为 0 的边。
③ 处应填( )。
quanzhi0infinity1正确答案A
【答案】A
【考点】图的边权存储
【解析】 输入的 `point1`、`point2` 和 `quanzhi` 分别表示有向边的起点、终点和权值,因此应令 `edg[point1][point2] = quanzhi`。
【易错点】 不能把已存在的边权重置为 0 或无穷大。
④ 处应填( )。
jdis[j]flag[j]i正确答案B
【答案】B
【考点】Dijkstra 选点
【解析】 枚举未确定最短路的顶点时,若发现 `dis[j]` 更小,就要把当前最小距离 `min` 更新为 `dis[j]`,并记录顶点 `u = j`。
【易错点】 `min` 保存的是距离值,不是顶点编号。
⑤ 处应填( )。
dis[u]edg[u][v]dis[u] + edg[u][v]infinity正确答案C
【答案】C
【考点】最短路松弛
【解析】 经顶点 到 的候选距离是 `dis[u] + edg[u][v]`。当它小于当前 `dis[v]` 时,应把 `dis[v]` 更新为这个候选值。
【易错点】 边权只是局部代价,还要加上源点到 的距离。
有一个容量为 10 的背包,另有 5 种物品,每种物品数量无限,其重量分别为 5, 4, 3, 2, 1,价值分别为 1, 2, 3, 4, 5。设计算法,实现背包内物品价值最大。代码如下(输出 50)。
1 | #include <iostream>
2 | #include <algorithm>
3 | using namespace std;
4 | int main() {
5 | int total_weight = 10;
6 | int w[6] = {0, 5, 4, 3, 2, 1};
7 | int v[6] = {0, 1, 2, 3, 4, 5};
8 | int dp[11] = {①};
9 | for (int i = 1; i <= ②; i++)
10 | for (int j = w[i]; j <= ③; j++)
11 | dp[j] = ④;
12 | cout << ⑤ << endl;
13 | return 0;
14 | }① 处应填( )。
051015正确答案A
【答案】A
【考点】动态规划初始化
【解析】 `int dp[11] = {0}` 会把整个数组初始化为 0,表示容量为 0 或尚未装入物品时的最大价值为 0。
【易错点】 花括号中的单个 0 会初始化整个数组,不只是 `dp[0]`。
② 处应填( )。
561015正确答案A
【答案】A
【考点】完全背包物品枚举
【解析】 数组中有效物品编号为 1 到 5,所以外层循环应满足 `i <= 5`,恰好枚举全部 5 种物品。
【易错点】 编号 0 是占位元素,不是一种物品。
③ 处应填( )。
561015正确答案C
【答案】C
【考点】完全背包容量枚举
【解析】 背包总容量由 `total_weight = 10` 给出,内层循环需从当前物品重量递增枚举到容量 10,因此③填 10。
【易错点】 完全背包的容量循环递增,但上界仍是背包总容量。
④ 处应填( )。
dp[j] + v[i]dp[j - w[i]] + v[i]min(dp[j], dp[j - w[i]] + v[i])max(dp[j], dp[j - w[i]] + v[i])正确答案D
【答案】D
【考点】完全背包状态转移
【解析】 容量 时,要在不选当前物品的 `dp[j]` 与再选一件当前物品的 `dp[j-w[i]] + v[i]` 之间取较大值,因此使用 `max`。
【易错点】 完全背包允许重复选择,所以同一轮使用已经更新过的较小容量状态。
⑤ 处应填( )。
v[10]dp[10]w[10]total_weight正确答案B
【答案】B
【考点】动态规划结果读取
【解析】 `dp[j]` 表示容量为 时可获得的最大价值,目标背包容量为 10,所以最终应输出 `dp[10]`,其值为 50。
【易错点】 `v[10]` 和 `w[10]` 超出有效物品编号范围。