一、单项选择题
(共 15 题,每题 2 分,共计 30 分;每题有且仅有一个正确选项)
CSPJ-2026-R1-Mock-3
试卷解析总览,可直接查看每题答案与解析。
(共 15 题,每题 2 分,共计 30 分;每题有且仅有一个正确选项)
在计算机内部,传送、存储和加工处理数据或指令都是以( )形式进行的。
正确答案A
【答案】A
【考点】二进制编码
【解析】 计算机内部的数字电路用两个稳定状态表示信息,因此数据和指令都以二进制码传送、存储和处理。
【易错点】 进制转换是表示方式,计算机底层统一采用二进制。
计算机的软件系统通常分为( )。
正确答案C
【答案】C
【考点】软件系统分类
【解析】 计算机软件系统通常分为系统软件和应用软件两大类。系统软件负责管理资源并为应用提供运行环境。
【易错点】 硬件系统与软件系统是整个计算机系统的分类,不是软件系统内部分类。
关于五寸软盘读写孔,正确的说法是( )。
正确答案C
【答案】C
【考点】软盘写保护
【解析】 五寸软盘的读写孔相当于写保护开关;孔被封住时介质处于只读状态,不能删除或改写文件。
【易错点】 该孔只控制写权限,数据并不是从孔中读写的。
一棵二叉树的中序遍历序列为 DGBAECHF,后序遍历序列为 GDBEHFCA,则前序遍历序列为( )。
正确答案B
【答案】B
【考点】二叉树遍历
【解析】 后序序列末尾确定根为 A。结合中序与后序可依次还原左子树前序为 BDG、右子树前序为 CEFH,所以整树前序为 ABDGCEFH。
【易错点】 每次都要先用后序末尾找根,再用中序划分左右子树。
下列叙述中错误的是( )。
正确答案B
【答案】B
【考点】计算机使用与维护
【解析】 强磁场、频繁开关和长期闲置都可能损害设备;计算机正常连续运行并不要求每隔几小时关机,因此 B 的说法错误。
【易错点】 不要把适当休息误解成必须定时彻底关机。
计算机网络最主要的优点是( )。
正确答案B
【答案】B
【考点】计算机网络
【解析】 计算机网络把分散的计算机和设备连接起来,最主要的优势是共享硬件、软件和数据等资源。
【易错点】 运算速度、精度和单机存储容量并不是网络最核心的优势。
下列 4 个不同进制表示的数中,最大的一个数是( )。
正确答案C
【答案】C
【考点】进制转换
【解析】 四个数换算成十进制分别为 220.1、219.5、220.125、220.0625,因此八进制的 最大。
【易错点】 小数部分也要按对应进制的负次幂换算。
为了区分汉字与 ASCII 码,计算机中汉字编码的最高位为( )。
正确答案A
【答案】A
【考点】字符编码
【解析】 ASCII 字符字节的最高位通常为 0;汉字交换码使用最高位为 1 的字节,以便与 ASCII 码区分。
【易错点】 题目问的是用于区分的最高位,不是字符占用的字节数。
一般来说,在 TCP/IP 协议族中 IP 提供的服务属于( )。
正确答案D
【答案】D
【考点】TCP/IP 分层
【解析】 IP 协议负责寻址与分组转发,属于 TCP/IP 的网络层。
【易错点】 TCP 属于传输层,不要由 TCP/IP 的组合名称误判 IP 所在层。
通信时,模拟信号也可以用数字信道来传输,能实现模拟信号与数字信号之间转换功能的是( )。
正确答案C
【答案】C
【考点】调制解调器
【解析】 Modem 即调制解调器,用于在模拟信号与数字信号之间进行调制和解调转换。
【易错点】 D/A、A/D 表示单向转换过程;题目所指的完整通信设备是 Modem。
一个栈的输入顺序为 1, 2, 3, 4, 5,下列序列中可能是栈的输出序列的是( )。
正确答案C
【答案】C
【考点】栈的出栈序列
【解析】 序列 21543 可通过依次压入 1、2 后弹出 2、1,再压入 3、4、5 后弹出 5、4、3 得到。
【易错点】 栈遵循后进先出,需按给定入栈顺序逐步模拟。
不属于 Internet 的功能的是( )。
正确答案D
【答案】D
【考点】Internet 功能
【解析】 Internet 可以支持聊天、远程教育和资料查询等信息服务,但不能传送物理能量。
【易错点】 网络传输的是数字信息,不是物质或能量。
下列关于计算机病毒的特性的描述中,( )不是正确的。
正确答案C
【答案】C
【考点】计算机病毒特性
【解析】 计算机病毒具有潜伏性、传染性和危害性;高速性不是病毒的基本特性。
【易错点】 传播速度可能很快,但这不等同于教材中的病毒特性。
下面不属于网络操作系统的是( )。
正确答案D
【答案】D
【考点】网络操作系统
【解析】 UNIX、Windows NT 和 NetWare 都可提供网络操作系统功能;DOS 是面向单机的磁盘操作系统。
【易错点】 名称中含有操作系统并不代表它具备网络操作系统功能。
根据《计算机软件保护条例》,中国公民开发的软件享有著作权的情形是( )。
正确答案A
【答案】A
【考点】软件著作权
【解析】 中国公民独立开发的软件自完成之日起依法享有著作权,不以开发地点或是否发表为前提。
【易错点】 著作权取得不要求先公开发表。
(程序输入不超过数组或字符串定义的范围;判断题正确填 ✓,错误填 ✗;除特殊说明外,判断题每题 2 分,选择题每题 3 分。)
1 | #include <bits/stdc++.h>
2 | using namespace std;
3 | const int Maxn = 10005;
4 | int n, b[Maxn];
5 | void mergesort(int *a, int l, int r) {
6 | if (l == r) return;
7 | int mid = l + r >> 1;
8 | mergesort(a, l, mid), mergesort(a, mid + 1, r);
9 | int i = l, j = mid + 1, cnt = 0;
10 | while (i <= mid && j <= r) {
11 | if (a[i] <= a[j]) b[++cnt] = a[i++];
12 | else b[++cnt] = a[j++];
13 | }
14 | while (i <= mid) b[++cnt] = a[i++];
15 | while (j <= r) b[++cnt] = a[j++];
16 | for (i = l; i <= r; i++) a[i] = b[i - l + 1];
17 | }
18 |
19 | int a[Maxn];
20 | int main(void) {
21 | cin >> n;
22 | for (int i = 1; i <= n; i++) cin >> a[i];
23 | mergesort(a, 1, n);
24 | for (int i = 1; i <= n; i++) cout << a[i] << (i == n ? '\n' : ' ');
25 | return 0;
26 | }(1 分)该算法中参数 `int *a` 采用的不是传值方式。
正确答案错误
【答案】错误
【考点】参数传递
【解析】 `int *a` 形参本身仍是按值传递,只是复制后的指针与实参指向同一数组,因此函数内可以修改数组元素。题干说“不是传值方式”,故错误。
【易错点】 能修改指向对象不等于指针形参采用引用传递。
(1 分)该算法输出最后会换行。
正确答案正确
【答案】正确
【考点】条件运算符与换行
【解析】 输出最后一个元素时 `i == n` 为真,条件表达式选择字符 `\n`,所以最后会换行。
【易错点】 字符 `\n` 是换行符,不是普通的反斜杠和字母 n。
该算法中 `mergesort` 函数的时间复杂度为 。
正确答案正确
【答案】正确
【考点】归并排序复杂度
【解析】 归并排序递归深度为 ,每层合并处理 个元素,总时间复杂度为 。
【易错点】 不要只看一次合并是线性的而忽略递归层数。
如果输入为 `5 4 3 9 7 8`,则输出为 `3 4 7 8 9`。
正确答案正确
【答案】正确
【考点】归并排序结果
【解析】 程序对 5 个输入数进行升序归并排序,因此输出 `3 4 7 8 9`。
【易错点】 输入开头的 5 是元素个数,不参与排序。
下列选项中与 `i == n ? '\n' : ' '` 功能相同的是( )。
i != 1 ? '\n' : ' '"\n "[i == n]"\n "[i != n]' '正确答案C
【答案】C
【考点】字符串下标与条件表达式
【解析】 在 `"\n "[i != n]` 中,`i == n` 时下标为 0,取换行符;否则下标为 1,取空格,功能与原表达式相同。
【易错点】 布尔值作为数组下标时,假为 0、真为 1。
该算法在最坏情况下的时间复杂度与( )算法相同。
正确答案D
【答案】D
【考点】排序复杂度
【解析】 归并排序和堆排序的最坏时间复杂度都为 。
【易错点】 快速排序平均为 ,但最坏可退化为 。
1 | #include <bits/stdc++.h>
2 | using namespace std;
3 | int i, j, k, n, m, f[10010], p1, p2, p3;
4 | int find(int k) {
5 | if (f[k] == k) return k;
6 | return f[k] = find(f[k]);
7 | }
8 | int main() {
9 | cin >> n >> m; // 假设 n, m 同量级
10 | for (i = 1; i <= n; i++) f[i] = i;
11 | for (i = 1; i <= m; i++) {
12 | cin >> p1 >> p2 >> p3;
13 | if (p1 == 1)
14 | f[find(p2)] = find(p3);
15 | if (p1 == 2) {
16 | if (find(p2) == find(p3))
17 | printf("Y\n");
18 | else
19 | printf("N\n");
20 | }
21 | }
22 | return 0;
23 | }该算法中 `p1` 的作用是确定操作类型。
正确答案正确
【答案】正确
【考点】并查集操作
【解析】 程序中 `p1 == 1` 表示合并两个集合,`p1 == 2` 表示查询两点是否连通,因此 `p1` 用于确定操作类型。
【易错点】 `p2`、`p3` 才是操作涉及的两个节点。
去掉 `for (i = 1; i <= n; i++) f[i] = i;` 对该算法没有影响。
正确答案错误
【答案】错误
【考点】并查集初始化
【解析】 初始化令每个节点的父节点为自身,表示最初互不连通。若删除,作为全局数组的 `f` 全为 0,集合关系会完全改变。
【易错点】 全局数组虽会自动清零,但 0 不是这里所需的父节点初值。
如果输入为 `2 2 1 1 2 2 1 2`,则输出为 `Y`。
正确答案正确
【答案】正确
【考点】并查集合并与查询
【解析】 输入先执行 `1 1 2` 合并节点 1、2,再执行 `2 1 2` 查询,两点已经连通,所以输出 Y。
【易错点】 先按 `n m` 划分输入,再逐条读取三个操作参数。
如果输入为 `2 1 2 1 2`,则输出为 `N`。
正确答案正确
【答案】正确
【考点】并查集连通性
【解析】 输入只有一次 `2 1 2` 查询,没有执行合并,节点 1、2 初始不连通,所以输出 N。
【易错点】 `m=1` 表示后面只有一条操作。
该算法的时间复杂度为( )。
正确答案A
【答案】A
【考点】路径压缩复杂度
【解析】 按题目给定分析,仅做路径压缩的并查集一次操作最坏按 计, 次操作为 。
【易错点】 本题没有采用选项中常见的反阿克曼函数表达式,应按试卷设定选择。
把 `return f[k] = find(f[k]);` 改成 `return find(f[k]);`,则最坏情况下算法的时间复杂度为( )。
正确答案B
【答案】B
【考点】取消路径压缩
【解析】 改成 `return find(f[k]);` 后不再回写父节点,最坏时查找链长为 , 次操作为 。
【易错点】 递归仍能找到根,但不会缩短后续查询路径。
1 | #include <bits/stdc++.h>
2 | using namespace std;
3 | int t, x[100], a[100];
4 | void work(int d, int i, int n) {
5 | int k;
6 | if (n == 1) {
7 | for (k = 0; k < d; k++)
8 | printf("%3d", a[k]);
9 | printf("\n");
10 | } else for (k = i; k < t; k++)
11 | if (n % x[k] == 0) {
12 | a[d] = x[k];
13 | work(d + 1, k, n / x[k]);
14 | }
15 | }
16 |
17 | int main() {
18 | int i, k, n;
19 | cin >> n;
20 | for (i = n; i > 1; i--)
21 | if (n % i == 0) x[t++] = i;
22 | work(0, 0, n);
23 | return 0;
24 | }`main()` 函数里的 `for` 循环的作用是求出 的所有因数。
正确答案错误
【答案】错误
【考点】因数枚举
【解析】 主函数循环只枚举从 到 2 的因数,没有把 1 加入数组,因此并未求出 的所有因数。
【易错点】 1 也是任何正整数的因数。
该程序的作用是对 进行素因数分解。
正确答案错误
【答案】错误
【考点】乘积分解
【解析】 递归枚举的是把 写成若干个大于 1 的因数乘积的方案,因子不要求都是质数,所以不是单纯的素因数分解。
【易错点】 例如 72 的方案中可以出现 36、24、18 等合数。
去掉 `printf("%3d", a[k]);` 中的 `3` 对程序没有影响。
正确答案错误
【答案】错误
【考点】格式化输出
【解析】 `%3d` 指定最小字段宽度为 3;去掉 3 会改变数字前的补空格,从而改变输出格式。
【易错点】 字段宽度不改变数值,但仍会改变程序输出。
去掉 `if (n % x[k] == 0)` 对程序有影响。
正确答案正确
【答案】正确
【考点】递归合法性判断
【解析】 递归参数 `n` 会不断除去已选因数,此时剩余值未必还能被后续的 `x[k]` 整除;删除判断会进入非法分解,因此会影响程序。
【易错点】 `x[k]` 是原始输入的因数,不保证是每个递归状态中剩余数的因数。
如果输入为 2,那么输出为( )。
正确答案A
【答案】A
【考点】程序输出模拟
【解析】 输入 2 时数组中只有因数 2,递归选择 2 后剩余值为 1,于是输出唯一一行 `2`。
【易错点】 程序不会把因数 1 存入或输出。
如果输入为 72,那么输出的非回车字符有( )行。
正确答案C
【答案】C
【考点】递归枚举计数
【解析】 程序对 72 枚举出 16 种非增因数乘积分解方案,因此共有 16 行非空输出。
【易错点】 计数时不要漏掉 `72` 本身,也不要把因子顺序不同的同一方案重复计算。
输入 个整点在平面上的坐标。每个点可以控制所有位于它左下方的点(即 、 坐标都比它小的点),它可以控制的点的数目称为“战斗力”。依次输出每个点的战斗力,最后输出战斗力最高的点的编号(如果若干个点的战斗力并列最高,则输出编号最大的那个)。
1 | #include <iostream>
2 | using namespace std;
3 | const int SIZE = 100;
4 | int x[SIZE], y[SIZE], f[SIZE];
5 | int n, i, j, max_f, ans;
6 | int main() {
7 | cin >> n;
8 | for (i = 1; i <= n; i++) cin >> x[i] >> y[i];
9 | max_f = 0;
10 | for (i = 1; i <= n; i++) {
11 | f[i] = ①;
12 | for (j = 1; j <= n; j++) {
13 | if (x[j] < x[i] && ②)
14 | ③;
15 | }
16 | if ④ {
17 | max_f = f[i];
18 | ⑤;
19 | }
20 | }
21 | for (int i = 1; i <= n; i++) cout << f[i] << endl;
22 | cout << ans << endl;
23 | return 0;
24 | }① 处应填( )。
01iINT_MAX正确答案A
【答案】A
【考点】计数数组初始化
【解析】 每个点的战斗力都应从 0 开始累计,所以处理第 个点前应令 `f[i] = 0`。
【易错点】 原卷此处漏印了下标 `[i]`,结合后续使用及答案解析可确定初始化对象是 `f[i]`。
② 处应填( )。
y[j] <= y[i]y[j] < y[i]y[j] > y[i]y[j] >= y[i]正确答案B
【答案】B
【考点】左下方判定
【解析】 点 位于点 左下方要求两个坐标都严格更小;已有 `x[j] < x[i]`,还需 `y[j] < y[i]`。
【易错点】 “左下方”不包含横坐标或纵坐标相等的点。
③ 处应填( )。
ans = if[i]++f[i]--ans++正确答案B
【答案】B
【考点】战斗力计数
【解析】 每发现一个满足条件的点 ,就应把当前点 的战斗力加 1,即执行 `f[i]++`。
【易错点】 `ans` 保存最终点编号,不用于累计战斗力。
④ 处应填( )。
f[i] > max_ff[i] >= max_ff[i] < max_ff[i] <= max_f正确答案B
【答案】B
【考点】最大值与并列规则
【解析】 需要选择最大战斗力;并列时取编号最大的。由于 从小到大枚举,条件应为 `f[i] >= max_f`,相等时也更新。
【易错点】 若只用 `>`,并列时会保留较小编号。
⑤ 处应填( )。
ans++ans += max_fans = ians = max_f正确答案C
【答案】C
【考点】最优编号记录
【解析】 更新最大战斗力时,应同步记录当前点编号,所以填 `ans = i`。
【易错点】 `ans` 存编号,不是战斗力数值。
输入两个正整数 (,),在 中任取 个数,按字典序从小到大输出所有这样的排列。
样例输入:
3 2样例输出:
1 2
1 3
2 1
2 3
3 1
3 2 1 | #include <iostream>
2 | #include <cstring>
3 | using namespace std;
4 | const int SIZE = 25;
5 | bool used[SIZE];
6 | int data[SIZE];
7 | int n, m, i, j, k;
8 | bool flag;
9 |
10 | int main() {
11 | cin >> n >> m;
12 | memset(used, false, sizeof(used));
13 | for (i = 1; i <= m; i++) {
14 | data[i] = i;
15 | used[i] = true;
16 | }
17 | flag = true;
18 | while (flag) {
19 | for (i = 1; i <= m - 1; i++)
20 | cout << data[i] << " ";
21 | cout << data[m] << endl;
22 | flag = ①;
23 | for (i = m; i >= 1; i--) {
24 | ②;
25 | for (j = data[i] + 1; j <= n; j++)
26 | if (!used[j]) {
27 | used[j] = true;
28 | data[i] = ③;
29 | flag = true;
30 | break;
31 | }
32 | if (flag) {
33 | for (k = i + 1; k <= m; k++)
34 | for (j = 1; j <= ④; j++)
35 | if (!used[j]) {
36 | data[k] = j;
37 | used[j] = true;
38 | break;
39 | }
40 | ⑤;
41 | }
42 | }
43 | }
44 | return 0;
45 | }① 处应填( )。
falsetrue1-1正确答案A
【答案】A
【考点】循环状态初始化
【解析】 每轮输出当前排列后,先假设不存在下一排列,令 `flag = false`;只有成功找到可增大的位置时才重新设为 true。
【易错点】 若一开始仍为 true,最后一个排列后循环可能无法正确结束。
② 处应填( )。
used[i] = truedata[i] = iused[data[i]] = trueused[data[i]] = false正确答案D
【答案】D
【考点】排列状态维护
【解析】 尝试增大第 位前,应先释放当前值,使其可在后续位置重新使用,因此执行 `used[data[i]] = false`。
【易错点】 释放的是 `data[i]` 所代表的数值,不是位置下标 。
③ 处应填( )。
jitruefalse正确答案A
【答案】A
【考点】下一字典序排列
【解析】 内层循环找到第一个可用的更大值 `j` 后,应令 `data[i] = j`。
【易错点】 `used[j]` 记录占用状态,而 `data[i]` 必须保存实际排列值。
④ 处应填( )。
nmij正确答案A
【答案】A
【考点】贪心补全后缀
【解析】 第 位增大后,后续各位要按从小到大选择整个值域 到 中尚未使用的数,所以循环上界填 `n`。
【易错点】 候选值范围由 决定,排列长度 只决定位置数。
⑤ 处应填( )。
return 0exitcontinuebreak正确答案D
【答案】D
【考点】循环控制
【解析】 成功构造出下一排列后应跳出从后向前寻找位置的 `for` 循环,返回 `while` 顶部输出新排列,因此填 `break`。
【易错点】 `continue` 只会继续当前 `for`,可能再次修改已经构造好的排列。