GESP 客观题评测系统

试卷解析 · 理解每一步

提高组 CSP-S 2026 初赛模拟卷 6

CSPS-2026-R1-Mock-6

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

一、单项选择题

第 1 题(单选题,2 分)

在以下各项中,( )不是 CPU 的组成部分。

A.
控制器
B.
运算器
C.
寄存器
D.
主板

正确答案D

解析详情
答案 D计算机基础与数据结构算法
思路与推导
  1. 控制器、运算器、寄存器均为 CPU 的组成部分。主板是连接各元件的电路板。

第 2 题(单选题,2 分)

(2017) 8_{8} + (1234) 10_{10} 的结果是()。

A.
(8E2)16(8E2)_{16}
B.
(100011100001)2(100011100001)_{2}
C.
(8E0)16(8E0)_{16}
D.
(100011100011)2(100011100011)_{2}

正确答案B

解析详情
答案 B计算机基础与数据结构算法
思路与推导
  1. 2017 转十进制为 2×83+1×81+7×80=1024+8+7=10392 \times 8^{3} + 1 \times 8^{1} + 7 \times 8^{0} = 1024 + 8 + 7 = 1039, 1039+1234=22731039 + 1234 = 2273. 根据奇偶性排除选项 A 和 C, 再根据模 4 余 1 排除选项 D. 也可以逐个选项验证。

第 3 题(单选题,2 分)

设 A=B=trueA = B = \text{true}, C=D=falseC = D = \text{false},则下列逻辑运算表达式的值为假的是()。

A.
(!A && B) || (C && D || A)
B.
!((A && B) || C) && D)
C.
A && (B || C || D) || D
D.
(A && (D || C)) && B

正确答案D

解析详情
答案 D计算机基础与数据结构算法
思路与推导
  1. 逐个代入验证即可。

第 4 题(单选题,2 分)

已知一个栈的入栈序列为 1,⋯ ,n1, \cdots, n,出栈序列为 p1,⋯ ,pnp_{1}, \cdots, p_{n},若 p1=np_{1}=n,则 pi=()p_{i}=()。

A.
i
B.
n-i
C.
n−i+1n-i+1
D.
不确定

正确答案C

解析详情
答案 C计算机基础与数据结构算法
思路与推导
  1. n 最后入栈,最先出栈,故出栈顺序为 n,n−1,⋯ ,1n, n-1, \cdots, 1。出栈顺序和入栈顺序相反,所以出栈的第 i 个元素就是从 n 开始倒着数的第 i 个元素,也就是 n−i+1n-i+1。

第 5 题(单选题,2 分)

设 S=“abbccce”S = \text{“abbccce”},其不同的非空子串有( )个。

A.
19
B.
17
C.
16
D.
18

正确答案A

解析详情
答案 A计算机基础与数据结构算法
思路与推导
  1. 非空子串数量 n(n+1)/2=6×7/2=21n(n+1)/2 = 6 \times 7/2 = 21,子串 b 和 c 出现了 2 次,所以 21 - 2 = 19。

第 6 题(单选题,2 分)

在 C++ 中, 1252=()125^{2} = (\quad)。

A.
127
B.
128
C.
15625
D.
126

正确答案A

解析详情
答案 A计算机基础与数据结构算法
思路与推导
  1. 125 = (1111101),异或2相当于二进制倒数第2位取反,这里就是加2,得127。

第 7 题(单选题,2 分)

设某算法的计算时间表示为递推关系式 T(n)=2T(n/2)+nT(n)=2T(n/2)+n (n 为正整数),且 T(0)=1T(0)=1,则该算法的时间复杂度为()。

A.
O(n)O(n)
B.
O(n2)O(n^{2})
C.
O(nlog⁡n)O(n\log n)
D.
O(log⁡n)O(\log n)

正确答案C

解析详情
答案 C计算机基础与数据结构算法
思路与推导
  1. 根据主定理结论, O(nlog22)=O(n)O(n^{log_{2}2}) = O(n), T(n)=O(nlog⁡n)T(n) = O(n \log n)。如不知道主定理,也可代入一个 n 估算,例如 n = 1024。

第 8 题(单选题,2 分)

下列有关二叉树的叙述(设根节点为第1层)中,不正确的是()。

A.
二叉树的深度为 k,那么最多有 2k−12^{k}-1 个节点
B.
在二叉树的第 i 层上,最多有 2i−12^{i}-1 个节点
C.
完全二叉树一定是满二叉树
D.
堆是完全二叉树

正确答案C

解析详情
答案 C计算机基础与数据结构算法
思路与推导
  1. 完全二叉树的最后一层不一定是满的,满二叉树是特殊的完全二叉树。

第 9 题(单选题,2 分)

下列排序算法中,平均时间复杂度是 O(n2)O(n^{2}) 的是()。

A.
快速排序
B.
插入排序
C.
归并排序
D.
堆排序

正确答案B

解析详情
答案 B计算机基础与数据结构算法
思路与推导
  1. 插入排序是 O(n2)O(n^{2}),其他是 O(nlog⁡n)O(n \log n)。快速排序虽然最坏情况下的时间复杂度是 O(n2)O(n^{2}),但这里问的是平均情况。

第 10 题(单选题,2 分)

下列图中一定可以进行黑白着色,使得相邻节点的颜色不同的是()。

A.
树
B.
基环树
C.
连通图
D.
欧拉图

正确答案A

解析详情
答案 A计算机基础与数据结构算法
思路与推导
  1. 把树中深度为奇数的节点染成黑色,深度为偶数的节点染成白色即可。充要条件是二分图。树是一种特殊的二分图;基环树是二分图当且仅当唯一的环是偶阶环;选项 C 和 D 则与二分图没什么关联。

第 11 题(单选题,2 分)

下列不是操作系统的是()。

A.
Linux
B.
Windows
C.
Android
D.
WPS

正确答案D

解析详情
答案 D计算机基础与数据结构算法
思路与推导
  1. WPS 是办公软件。

第 12 题(单选题,2 分)

下列关于算法的叙述中,错误的是()。

A.
算法代表着用系统的方法描绘解决问题的策略机制
B.
一个算法的好坏,只需要从时间复杂度这一方面进行考虑
C.
一个算法必须具有有穷性、可行性、正确性、输入和输出
D.
对于一些 NP 完全问题,现在未能找到有效的算法来解决

正确答案B

解析详情
答案 B计算机基础与数据结构算法
思路与推导
  1. 衡量一个算法的好坏,性能方面至少包括时间复杂度和空间复杂度。广义上说还有可读性、容错性等更多参考指标。说“只需要考虑时间复杂度”显然是不对的。

第 13 题(单选题,2 分)

下列叙述中正确的是()。

A.
线性表是线性结构
B.
栈与队列是非线性结构
C.
线性链表是非线性结构
D.
二叉树是线性结构

正确答案A

解析详情
答案 A计算机基础与数据结构算法
思路与推导
  1. 栈、队列是线性结构,树是非线性结构。

第 14 题(单选题,2 分)

链表的( )操作需要 O(n)O(n) 时间复杂度的实现。

A.
插入
B.
定位
C.
删除
D.
合并

正确答案B

解析详情
答案 B计算机基础与数据结构算法
思路与推导
  1. 链表的定位操作的时间复杂度是 O(n)O(n),因为没有全局下标访问功能,只有局部的前驱/后继功能。插入、删除、合并操作的时间复杂度是 O(1)O(1)。

第 15 题(单选题,2 分)

在 NOI 比赛中,不可以带入考场的是()。

A.
键盘
B.
空白纸张
C.
U 盘
D.
铅笔

正确答案C

解析详情
答案 C计算机基础与数据结构算法
思路与推导
  1. U 盘是必然不能带入的,笔可以带。纸张一般考场会发也不自带,但选项说的是空白纸张,相比之下还是 U 盘更明确。对于键盘则没有规定(也不可能有人自带键盘)。

二、阅读程序(1)

{1}

#include <iostream>
using namespace std;
int n, k, ans;

int main() {
    cin >> n >> k; // 保证 n, k 是非负整数,且在 int 范围内
    int ans = 0;
    while (n) {
        if (n % k > 0) ans++;
        n /= k;
    }
    cout << ans << endl;
    return 0;
}

第 16 题(判断题,1 分)

把n%k>0改成n%k不影响程序运行结果。()

正确答案正确

解析详情
答案 正确进制位数统计
思路与推导
  1. int 强制转为 bool,当且仅当非零时为 true,而这里 n%k 不可能为负数。

第 17 题(判断题,2 分)

输入的 k 需要大于 1,否则程序可能无法正常运行。 ()

正确答案正确

解析详情
答案 正确进制位数统计
思路与推导
  1. k=0,则除数为0,k=1时,n/=k相当于没效果,会发生死循环。

第 18 题(判断题,2 分)

输入的 n 需要大于 0,否则程序可能无法正常运行。 ()

正确答案错误

解析详情
答案 错误进制位数统计
思路与推导
  1. 输入 n=0 时程序可以正常运行,输出 0。

第 19 题(判断题,2 分)

该算法的时间复杂度为 O(log⁡n)O(\log n)。 ()

正确答案正确

解析详情
答案 正确进制位数统计
思路与推导
  1. n 在 k 进制意义下的位数严格说来是 log⁡kn\log_{k}n,但根据换底公式,底数只影响常数系数。

第 20 题(单选题,3 分)

输入 125 5 时,输出结果为()。

A.
1
B.
2
C.
3
D.
4

正确答案A

解析详情
答案 A进制位数统计
思路与推导
  1. 125=(1000)5125=(1000)_{5}。

第 21 题(单选题,3 分)

当 n 在 int 范围内时,输出的位数最大值为()。

A.
29
B.
30
C.
31
D.
32

正确答案C

解析详情
答案 C进制位数统计
思路与推导
  1. n 最大为 231−12^{31}-1,k=2 时输出 1 的位数最大为 31。

二、阅读程序(2)

#include <iostream>
using namespace std;

int equationCount(int n, int m) {
    if (n == 1 || m == 1) return 1;
    if (n < m) return equationCount(n, n);
    if (n == m) return 1 + equationCount(n, n - 1);
    return equationCount(n, m - 1) + equationCount(n - m, m);
}

int main() { // 本题不需要考虑数值溢出的可能性
    int n;
    cin >> n;
    cout << equationCount(n, n) << endl;
    return 0;
}

第 22 题(判断题,1 分)

输入的 n 必须为正整数,否则程序无法正常运行。 ()

正确答案正确

解析详情
答案 正确整数拆分递归
思路与推导
  1. 递归边界只有 n=m=1,而主函数调用又是 n,n。如果 n 是 0 或负数,递归时第 2 个参数 m 永远不会变大,也就不会达到 m==1,递归将陷入死循环而栈溢出。

第 23 题(判断题,2 分)

去掉 if (n == m) return 1 + equationCount(n, n-1); 这句,对输出无影响。()

正确答案错误

解析详情
答案 错误整数拆分递归
思路与推导
  1. 不提前判断 n==m,这种情况就会调用 equationcount(n-m,m),导致参数 n 变成 0 从而陷入递归死循环。

第 24 题(判断题,2 分)

若主函数改为调用 equationCount(n, n+1),不影响程序运行结果。 ()

正确答案正确

解析详情
答案 正确整数拆分递归
思路与推导
  1. 逻辑是 n 的正整数拆分中加数本来就不会超过 n;从该代码看第二个 if 还是会调用到 (n,n) 的情形(为避免有人硬说 n=231−1n=2^{31}-1 引发 n+1 溢出,题目注释中特意说明了)。

第 25 题(判断题,2 分)

去掉 if (n < m) return equationCount(n, n); 这句,对输出无影响。 ( )

正确答案错误

解析详情
答案 错误整数拆分递归
思路与推导
  1. 同第23题一样的原因。

第 26 题(单选题,3 分)

输入7时,输出结果为()。

A.
12
B.
13
C.
14
D.
15

正确答案D

解析详情
答案 D整数拆分递归
思路与推导
  1. 如果能看出逻辑含义,则直接手动算出 7 的拆分方案即可;或者利用递推式 f(n,m)=f(n,m−1)+f(n−m,m)f(n,m)=f(n,m-1)+f(n-m,m) 推算。注意,手动推算用非递归方式更好,也就是按 n,m 从小到大计算。递归会有重复计算。

第 27 题(单选题,3 分)

该算法的时间复杂度为()。

A.
O(log⁡n)O(\log n)
B.
O(n)O(n)
C.
O(n2)O(n^{2})
D.
以上都不是

正确答案D

解析详情
答案 D整数拆分递归
思路与推导
  1. 由于没有使用记忆法,递归实际上相当于把所有方案都枚举了一遍(最后的答案都是从 return 1 那个分支贡献的),所以复杂度呈指数级。如果使用记忆法,则复杂度为 O(n2)O(n^{2})。

  2. 另外,拆分数的最优解法可以做到 O(nn)O(n\sqrt{n}),有两种做法:根号分治和五边形数定理。具体可自行调研。

二、阅读程序(3)

#include <iostream>
using namespace std;
const int maxn = 100000;
int a[maxn], b[maxn], n;

int Search(int num, int low, int high) {
    int mid;
    while (low <= high) {
        mid = (low + high) / 2;
        if (num >= b[mid]) low = mid + 1;
        else high = mid - 1;
    }
    return low;
}

int main() {
    int len, pos;
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    b[1] = a[1];
    len = 1;
    for (int i = 2; i <= n; i++) {
        if (a[i] >= b[len]) b[++len] = a[i];
        else {
            pos = Search(a[i], 1, len);
            b[pos] = a[i];
        }
    }
    cout << len << endl;
    return 0;
}

第 28 题(判断题,2 分)

输入的 a[i] 必须在 [1,n] 范围内。 ()

正确答案错误

解析详情
答案 错误最长不降子序列
思路与推导
  1. a[i] 值并没有作为任何数组的下标,只参与赋值和比大小,所以可以是 int 范围内的任意数。

第 29 题(判断题,2 分)

把 if (num >= b[mid]) low = mid + 1; 中的 mid + 1 改成 mid, 不影响程序运行结果。()

正确答案错误

解析详情
答案 错误最长不降子序列
思路与推导
  1. 因为 mid 是向下取整,所以如果改了,在 low+1=high 的情况下,就会出现 low=low 的赋值,造成死循环。

第 30 题(判断题,2 分)

当数组 a 单调不降时,输出为 1。()

正确答案错误

解析详情
答案 错误最长不降子序列
思路与推导
  1. 输出为 n,如果看不出算法逻辑,代入 n=2,a={1,2} 进行模拟也能判定。

第 31 题(判断题,2 分)

数组 b 内的元素始终单调不降。 ()

正确答案正确

解析详情
答案 正确最长不降子序列
思路与推导
  1. a 数组大于 b 数组最后一位数,就把 a 增加到 b 数组;如果小于,就找到 b 数组中第一个大于等于 a[i] 的数替换掉。这个过程保持 b 数组单调不降(随便写组数据模拟一下这个过程就明白了)。

第 32 题(单选题,3 分)

若输入以下数据,则输出为()。

20

1 20 2 19 3 18 4 17 5 16 6 15 7 14 8 13 9 12 10 11

A.
1
B.
10
C.
11
D.
20

正确答案C

解析详情
答案 C最长不降子序列
思路与推导
  1. 该序列的最长不降子序列为 1 2 3 4 5 6 7 8 9 10 11,长度为 11。

第 33 题(单选题,3 分)

该算法的时间复杂度为()。

A.
O(n)O(n)
B.
O(nlog⁡n)O(n \log n)
C.
O(n2)O(n^{2})
D.
O(n2log⁡n)O(n^{2} \log n)

正确答案B

解析详情
答案 B最长不降子序列
思路与推导
  1. 二分查找的复杂度 O(log⁡n)O(\log n),外层还有一个 i=1..n 的循环。

三、完善程序(1)

(精准覆盖问题)给定一个 N×MN \times M 的 0-1 矩阵,求选出其中的一些行,使对 1..M 的每一列,在所选行内有且只有一行该列为 1。例如如下的矩阵中第 1、4、5 行就是一种可行解。

11100001 10001110 10010110 00010010 00001100

输入数据:有多组数据,每组数据第一行的两个整数为 N, M;接下来 N 行,每行开头为一个整数 x,表示该行 1 的个数,其后的 x 个整数表示每个 1 所在的列编号。

输出要求:如果有解,随意输出一组可行解的行的集合,否则输出 NO。

#include <bits/stdc++.h>
using namespace std;
#define inf 1000000000
#define N 2005
#define M 2000005

int n, m, h[N], s[N], q[N];
int u[M], d[M], L[M], R[M], C[M], X[M];

void del(int c) {
    ①;
    ②;
    for (int i = d[c]; i != c; i = d[i])
        for (int j = R[i]; j != i; j = R[j])
            u[d[j]] = d[u[j]] = j, s[C[j]]--;
}

void add(int c) {
    L[R[c]] = R[L[c]] = c;
    for (int i = u[c]; i != c; i = u[i])
        for (int j = L[i]; j != i; j = L[j])
            u[d[j]] = d[u[j]] = j, s[C[j]]++;
}

bool dance(int k) {
    if (R[0] == 0) return true;
    int mn = inf, c;
    for (int i = R[0]; i; i = R[i])
        if (s[i] < mn) mn = s[i], c = i;
    ③;
    for (int i = d[c]; i != c; i = d[i]) {
        q[k + 1] = i;
        for (int j = R[i]; j != i; j = R[j]) ④;
        if (dance(k + 1)) return true;
        for (int j = L[i]; j != i; j = L[j]) ⑤;
    }
    add(c);
    return false;
}

第 34 题(单选题,3 分)

①处应填()。

A.
L[L[c]]=R[c];
B.
L[R[c]]=L[c];
C.
R[L[c]]=R[c];
D.
R[R[c]]=L[c];

正确答案B(另接受:C)

解析详情
答案 B精准覆盖与舞蹈链
思路与推导
  1. 此题和下一题的选项完全相同,代码也在一起,所以其实是四选二。根据函数名,这里是要“删 c”,容易猜测 L 和 R 是左右相邻项。那么删 c 就是:c 前驱的后继改为 c 的后继(这样就跳过了 c),后继的前驱改为 c 的前驱。所以这两道题分别选 B 和 C。

第 35 题(单选题,3 分)

②处应填()。

A.
L[L[c]]=R[c];
B.
L[R[c]]=L[c];
C.
R[L[c]]=R[c];
D.
R[R[c]]=L[c];

正确答案C(另接受:B)

解析详情
答案 C精准覆盖与舞蹈链
思路与推导
  1. 同上。这两题的答案互换也是对的。

第 36 题(单选题,3 分)

③处应填()。

A.
del(c);
B.
add(c);
C.
del(mn);
D.
add(mn);

正确答案A

解析详情
答案 A精准覆盖与舞蹈链
思路与推导
  1. dance(k) 是核心递归程序,就是枚举第 k 行选不选,③~⑤ 可以联合起来考虑。此题最简单的做法是根据 return 前的 add(c) 反向匹配,此处应是 del(c)。根据 del() 和 add() 中对 s 的操作,s 应该是表示某列的元素个数,而不是列编号,所以 mn 肯定是不对的,排除选项 C 和 D;而这里应该是选了这列,就要删掉,所以是 del()。

第 37 题(单选题,3 分)

④处应填()。

A.
add(j);
B.
del(j);
C.
add(C[j]);
D.
del(C[j]);

正确答案D

解析详情
答案 D精准覆盖与舞蹈链
思路与推导
  1. 最后这两题又是选项完全一样,当然此处答案不能互换,因为中间夹着一个递归调用。这两处明显应该是互逆的两次操作。再根据剪枝的逻辑,递归前应该是 del(),递归后是 add()。这里 C 是各列链表的头指针,这些头指针也组成一个列表,删整列就是在 C 这个头链表里删,所以选 D。

第 38 题(单选题,3 分)

⑤处应填()。

A.
add(j);
B.
del(j);
C.
add(C[j]);
D.
del(C[j]);

正确答案C

解析详情
答案 C精准覆盖与舞蹈链
思路与推导
  1. 见上题。

三、完善程序(2)

(树的直径)给定一棵有 n 个节点的树,每条边的长度为 wiw_{i}。树的直径指树中最长的简单路径,请求这棵树的直径长度。

求解方法:开始任选一个节点 u 作为起点进行 BFS,找到距离 u 最远的节点 s;再以节点 s 为起点,再次进行 BFS,找到距离 s 最远的节点 t。s 和 t 之间的路径长度就是树的直径长度。

#include <iostream>
#include <cstring>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 1005;
struct Node { int to, w, next; } edge[maxn * 2];
int head[maxn], tot, n, dis[maxn];
bool vis[maxn];
int que[maxn], first, last;

void init() {
    memset(head, -1, sizeof(head));
    tot = 0;
}

void addedge(int u, int v, int w) {
    edge[tot].to = v;
    edge[tot].w = w;
    edge[tot].next = head[u];
    head[u] = tot++;
}

int BFS(int u) {
    first = last = 0;
    memset(dis, inf, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    dis[u] = 0;
    vis[u] = 1;
    que[last++] = u;
    while (①) {
        u = que[first++];
        for (int i = head[u]; i != -1; i = edge[i].next) {
            int v = edge[i].to;
            if (②) {
                vis[v] = 1;
                que[last++] = v;
                ③;
            }
        }
    }
    int tmp = 1;
    for (int i = 2; i <= n; i++)
        if (④) tmp = i;
    return tmp;
}

int main() {
    int u, v, w, s, t;
    cin >> n;
    init();
    for (int i = 1; i < n; i++) {
        cin >> u >> v >> w;
        addedge(u, v, w);
        addedge(v, u, w);
    }
    s = BFS(1);
    ⑤;
    cout << dis[t] << endl;
    return 0;
}

第 39 题(单选题,3 分)

①处应填()。

A.
first < last
B.
first <= last
C.
first < last-1
D.
last == n

正确答案A

解析详情
答案 A树的直径
思路与推导
  1. 队列不为空。根据之前初始化队列的代码,约定为 last == first 为空。

第 40 题(单选题,3 分)

②处应填()。

A.
!vis[v]
B.
vis[v]
C.
vis[u]
D.
dis[v]

正确答案A

解析详情
答案 A树的直径
思路与推导
  1. BFS 入队条件是新的节点 v 未访问。

第 41 题(单选题,3 分)

③处应填( )。

A.
dis[v] = dis[u] + 1;
B.
dis[v] = dis[u] + edge[i].w;
C.
dis[u] = dis[v] + 1;
D.
dis[u] = dis[v] + edge[i].w;

正确答案B

解析详情
答案 B树的直径
思路与推导
  1. 从 u 走到 v,更新的是 dis[v],要加上边权。

第 42 题(单选题,3 分)

④ 处应填()。

A.
dis[i] < dis[tmp]
B.
dis[i] < tmp
C.
dis[i] > dis[tmp]
D.
dis[i] == tmp

正确答案C

解析详情
答案 C树的直径
思路与推导
  1. 打擂台,找到最大的 dis 的下标。

第 43 题(单选题,3 分)

⑤处应填( )。

A.
t = BFS(1);
B.
t = BFS(t);
C.
s = BFS(t);
D.
t = BFS(s);

正确答案A

解析详情
答案 A树的直径
思路与推导
  1. 要找与 s 距离最远的节点 t。