深色
全部展开
全部收起
答案速查
打印
单选
判断
一、考点地图
分类计数 3 题
动态规划 2 题
二项式定理 2 题
时间复杂度 2 题
引用 2 题
组合计数 2 题
最长公共子序列 2 题
Dijkstra 2 题
变量别名 1 题
并查集思想 1 题
乘法原理 1 题
递归 1 题
二、单选题逐题讲
单选题 1
分类计数;组合计数;乘法原理
某平台生成“取件码”由6个字符组成:前4位为数字(0 - 9),后2位为大写字母(A - Z),其中字母不能为 I、O。假设数字和字母均可重复使用,要求整个取件码中恰好有2个数字为奇数。共有多少种不同取件码?( )
A 1,440,000 B 2,160,000 C 2,535,000 D 8,640,000
展开解析
答案:B
分类计数 组合计数 乘法原理
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
前 4 位数字中恰好有 2 位奇数,先从 4 个位置里选出 2 个放奇数,有 C(4,2) =6 种。 每个奇数位有 5 种填法,每个偶数位也有 5 种填法,所以前 4 位共有 6 × 5^2 × 5^2 = 3750 种。 后 2 位是大写字母,且不能为 I、O,因此每位有 24 种选择,两位共有 24^2 = 576 种。 总数是 3750 × 576 = 2160000 ,所以选 B。
易错点: 容易只统计前 4 位里奇数的位置,却漏掉偶数位也各有 5 种可选数字。
单选题 2
归并排序;分治;递归区间
下列代码实现了归并排序(Merge Sort)的分治部分。为了正确地将数组 a 的 [left, right] 区间进行排序,横线处应该填入的是()。
复制 void merge_sort(int a[], int left, int right) {
if (left >= right) return;
int mid = (left + right) / 2;
merge_sort(a, left, mid);
___; // 在此处填入选项
merge(a, left, mid, right); // 合并操作
}
A merge_sort(a, mid, right) B merge_sort(a, mid + 1, right) C merge_sort(a, left, mid + 1) D merge_sort(a, mid - 1, right)
展开解析
答案:B
归并排序 分治 递归区间
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
归并排序把区间 [left, right] 分成左半段 [left, mid] 和右半段 [mid+1, right],分别排好序后再合并。 前一行已经递归处理了左半段,所以横线处应递归处理右半段,即 merge_sort(a, mid + 1, right)。 因此选 B。
易错点: 容易把右半段写成 [mid, right],这样会让 mid 被重复处理。
单选题 3
排列组合;分类讨论;限制条件计数
某社团有男生8人、女生7人。现需选出1名队长(性别不限)、1名副队长(性别不限)、2名宣传委员(两人无角色区别,且必须至少1名女生)。假如一人不能兼任多职,共有多少种不同选法?()
A 12012 B 11844 C 12474 D 11025
展开解析
答案:A
排列组合 分类讨论 限制条件计数
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
先选队长和副队长,这两个职务有先后顺序; 再从剩余人中选2名宣传委员,宣传委员没有顺序,且至少1名女生。 分三类讨论队长和副队长的性别。 两人都是男生时,有 8×7 种,剩下7女6男,宣传委员有 C(13,2) -C(6,2) =63 种。 一男一女时,有 8×7×2 种,剩下6女7男,宣传委员有 C(13,2) -C(7,2) =57 种; 两人都是女生时,有 7×6 种,剩下5女8男,宣传委员有 C(13,2) -C(8,2) =50 种。 总数是 8×7×63 + 8×7×2×57 + 7×6×50 = 12012 ,选 A。
易错点: 容易把队长和副队长当成无顺序,也容易忘记宣传委员“至少1名女生”的限制。
单选题 4
二项式定理;项的系数
二项式
(
2
𝑥
−
𝑦
)
8
(2x−y)
8
的展开式中
𝑥
5
𝑦
3
x
5
y
3
项的系数为()。
A -7168 B 7168 C -1792 D 1792
展开解析
答案:C
二项式定理 项的系数
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
在 (2x-y)^8 的展开式中,若要得到 x^5y^3,就要从8个因子里选3个取 -y,其余5个取 2x。 系数为 C(8,3) × 2^5 × (-1)^3 = 56 × 32 × (-1) = -1792。 所以选 C。
易错点: 容易漏掉 (-y)^3 里的负号。
单选题 5
Dijkstra;最短路;松弛操作
下面是使用邻接矩阵实现 Dijkstra 算法的核心片段,用于求单源最短路径。在找到当前距离起点最近的顶点 u 后,需要更新其邻接点 j 的距离。横线处应填入的代码是()。
复制 for (int j = 1; j <= n; j++) {
if (!visited[j] && graph[u][j] < INF) {
if (_____) { // 在此处填入选项
dis[j] = dis[u] + graph[u][j];
}
}
}
A dis[j] < dis[u] + graph[u][j] B dis[j] > dis[u] + graph[u][j] C graph[u][j] > dis[u] + dis[j] D dis[j] > graph[u][j]
展开解析
答案:B
Dijkstra 最短路 松弛操作
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
Dijkstra 更新邻点时,要比较原来的最短距离和经过 u 中转后的新距离。 如果 dis[u] + graph[u][j] 更小,就更新 dis[j]。 因此判断条件应为 dis[j] > dis[u] + graph[u][j],选 B。
易错点: 方向很容易写反。更新条件一定是“新路更短”。
单选题 6
动态规划;最长公共子序列;状态转移
下面程序使用动态规划求两个字符串的最长公共子序列(LCS)长度,横线处应填入的是()。
复制 #include <algorithm>
#include <string>
#include <vector>
using namespace std;
int lcs_len(const string &a, const string &b) {
int n = (int)a.size(), m = (int)b.size();
vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (a[i - 1] == b[j - 1])
dp[i][j] = dp[i - 1][j - 1] + 1;
else
// 在此处填入选项
return dp[n][m];
}
A dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; B dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]); C dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); D dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + 1;
展开解析
答案:C
动态规划 最长公共子序列 状态转移
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
LCS 中,当 a[i-1] == b[j-1] 时,dp[i][j] = dp[i-1][j-1] + 1。 当两个字符不相等时,当前位置不能同时选这两个字符,只能舍去其中一个,所以取 max(dp[i-1][j], dp[i][j-1])。 因此选 C。
易错点: 容易把不相等时也写成加1,那就变成错误转移了。
单选题 7
平面坐标;距离公式;C++ 表达式
已知两个点
𝐴
(
𝑥
1
,
𝑦
1
)
A(x
1
,y
1
)和
𝐵
(
𝑥
2
,
𝑦
2
)
B(x
2
,y
2
)在平面直角坐标系中的坐标。下列C++表达式中,能正确计算这两点之间直线距离的是( )。
A sqrt((x1 - x2) ^ 2 + (y1 - y2) ^ 2) B sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)) C pow(x1 - x2, 2) + pow(y1 - y2, 2) D abs(x1 - x2) + abs(y1 - y2)
展开解析
答案:B
平面坐标 距离公式 C++ 表达式
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
平面上两点 A(x1,y1)、B(x2,y2) 的距离公式是 sqrt((x1-x2)^2 + (y1-y2)^2)。 在 C++ 中不能直接用 ^2 表示平方,因为 ^ 是按位异或,不是乘方。 四个选项里,只有 sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)) 正确表达了距离公式,所以选 B。
易错点: 最容易错在把 ^ 当成乘方运算符。
单选题 8
引用;变量别名;赋值
已知 int a = 10;,执行 int &b = a; b = 20; 后,变量 a 的值是()。
A 10 B 20 C 30 D 编译错误
展开解析
答案:B
引用 变量别名 赋值
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
int &b = a 表示 b 是 a 的引用,也就是 a 的别名。 给 b 赋值 20,本质上就是给 a 赋值 20。 所以执行后 a=20,选 B。
易错点: 引用不是复制出一个新变量,而是给原变量起了一个别名。
单选题 9
时间复杂度;循环分析;求和估计
下列代码的时间复杂度(以n为自变量,忽略常数与低阶项)是()。
复制 long long s = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j * j <= i; j++) {
s += j;
}
}
A 𝑂
(
𝑛
)
O(n) B 𝑂
(
𝑛
log
𝑛
)
O(nlogn) C 𝑂
(
𝑛
𝑛
)
O(n
n
) D 𝑂
(
𝑛
2
)
O(n
2
)
展开解析
答案:C
时间复杂度 循环分析 求和估计
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
外层循环执行 n 次。 当固定 i 时,内层循环条件是 j*j <= i,所以 j 大约跑到 sqrt(i),内层复杂度是 O(sqrt(i) )。 总复杂度为 sum_{i=1}^{n} O(sqrt(i) ) = O(n sqrt(n) ),因此选 C。
易错点: 不能只看成两层循环就直接写成 O(n^2) ,关键要看内层到底跑多少次。
单选题 10
线性筛;质数筛法;最小质因子
下列程序实现了线性筛法(欧拉筛),用于在
𝑂
(
𝑛
)
O(n) 时间内求出
1
∼
𝑛
1∼n之间的所有质数。为了保证每个合数只被其最小质因子筛掉,横线处应填入的语句是()。
复制 for (int i = 2; i <= n; i++) {
if (!not_prime[i]) primes[++cnt] = i;
for (int j = 1; j <= cnt && i * primes[j] <= n; j++) {
not_prime[i * primes[j]] = true;
if (_____) break; // 在此处填入选项
}
}
A i + primes[j] == n B primes[j] > i C i % primes[j] == 0 D i % primes[j] != 0
展开解析
答案:C
线性筛 质数筛法 最小质因子
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
线性筛的关键是让每个合数只被它的最小质因子筛掉一次。 当枚举到 primes[j] 时,如果 i % primes[j] == 0,说明 primes[j] 已经是 i 的最小质因子,此时 i * primes[j] 也该在这里停止,后面更大的质数不应再参与当前 i 的筛除。 所以应写 if (i % primes[j] == 0) break;,选 C。
易错点: 如果不停下来,很多合数会被重复筛到,就不是线性筛了。
单选题 11
类与对象;继承;构造与析构
在 C++ 语言中,关于类的继承和访问权限,下列说法正确的是()。
A 派生类可以访问基类的 private 成员。 B 基类的 protected 成员在私有继承(private inheritance)后,在派生类中变为 public 。 C 派生类对象在创建时,会先调用基类的构造函数,再调用派生类自己的构造函数。 D 派生类对象在销毁时,会先调用基类的析构函数,再调用派生类自己的析构函数。
展开解析
答案:C
类与对象 继承 构造与析构
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
派生类对象创建时,必须先把基类部分构造好,再构造派生类自身,所以先调用基类构造函数,再调用派生类构造函数。 A 错在 private 成员不能被派生类直接访问。 B 错在 private 继承后,基类的 public 和 protected 成员在派生类中都变成 private,不会变成 public。 D 错在析构顺序相反,应该先析构派生类,再析构基类。 所以选 C。
易错点: 构造顺序和析构顺序正好相反,最容易混淆。
单选题 12
递归;递推;函数求值
当输入 6 时,下列程序的输出结果为()。
复制 #include <iostream>
using namespace std;
int f(int n) {
if (n <= 3) return n;
return f(n - 1) + f(n - 2) + 2 * f(n - 3);
}
int main() {
int n;
cin >> n;
cout << f(n) << endl;
return 0;
}
A 14 B 27 C 28 D 15
展开解析
答案:B
递归 递推 函数求值
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
由题意可得 f(1)=1,f(2)=2,f(3)=3。 继续往后算:f(4)=f(3)+f(2)+2f(1)=3+2+2=7 ,f(5)=f(4)+f(3)+2f(2)=7+3+4=14 ,f(6)=f(5)+f(4)+2f(3)=14+7+6=27 。 所以输出 27,选 B。
易错点: 容易把 2 * f(n-3) 漏乘2。
单选题 13
计数原理;分类计数;数位问题
从 1 到 999 这 999 个正整数中,十进制表示中数字 5 恰好出现一次的数有多少个?()
A 243 B 271 C 300 D 333
展开解析
答案:A
计数原理 分类计数 数位问题
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
把 1 到 999 看成3位数,不足3位的前面补0。 要求数字5恰好出现一次。 先选哪一位是5,有3种选法; 其余两位都不能是5,每位各有9种选法。 所以总数为 3 × 9 × 9 = 243 ,选 A。 补零不会带来问题,因为 000 本身不含数字5,不会被算进去。
易错点: 很多人会把一位数、两位数、三位数拆开分类,其实补零后统一处理更快。
单选题 14
二进制;lowbit;位运算
当输入 2023 时,下列程序的输出结果为()。
复制 #include <iostream>
using namespace std;
int main() {
int x, ans = 0;
cin >> x;
while (x != 0) {
x -= x & -x;
ans++;
}
cout << ans << endl;
return 0;
}
A 7 B 8 C 9 D 11
展开解析
答案:C
二进制 lowbit 位运算
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
表达式 x & -x 会取出 x 的最低位1。 循环中每次执行 x -= x & -x,就是把 x 的二进制表示中最低位的一个1消掉,因此循环次数等于二进制里1的个数。 2023 = 1024+512+256+128+64+32+4+2+1,共9个1,所以输出9,选 C。
易错点: 这段程序不是求二进制位数,而是求二进制中1的个数。
单选题 15
最小生成树;Kruskal;并查集思想
对连通无向图执行 Kruskal 算法。已按边权从小到大依次扫描到某条边
𝑒
=
(
𝑢
,
𝑣
)
e=(u,v)。此时在已经构建的部分 MST 结构中,
(
𝑢
,
𝑣
)
(u,v)已在同一连通块内。关于边
𝑒
e的处理,下列说法正确的是()。
A 必须选入 MST,否则可能不连通。 B 一定不能选入 MST(在此扫描顺序下)。 C 若后续出现更大的边权,可以回溯改选
𝑒
e。 D 只有当
𝑒
e是当前最小边时才能舍弃。
展开解析
答案:B
最小生成树 Kruskal 并查集思想
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
Kruskal 按边权从小到大扫描边。 如果当前边的两个端点已经在同一连通块中,再加入这条边就会形成环,因此这条边不能加入 MST。 所以这条边一定舍弃,选 B。
易错点: Kruskal 一旦判断会成环,这条边就直接丢弃,不存在后面再回头改选。
三、判断题逐题讲
判断题 1
加法原理;分类计数
若一项任务可用两种互斥方案完成:方案A有m种做法,方案B有n种做法,则总做法数为
𝑚
+
𝑛
m+n。
正确 正确 错误 错误
展开解析
答案:正确
加法原理 分类计数
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
任务可以用两种互斥方案完成,说明两类做法之间没有重叠。 方案A有 m 种,方案B有 n 种,总做法数就是 m+n。 所以本题正确。
易错点: 只有在“两类方案互斥”时,才能直接相加。
判断题 2
引用;C++ 基础语法
在C++语言中,引用一旦被初始化,就不能再改为引用另一个变量。
正确 正确 错误 错误
展开解析
答案:正确
引用 C++ 基础语法
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
引用在定义时必须绑定到某个变量,一旦绑定完成,就不能再改成引用别的变量。 后续对引用赋值,是修改它所绑定的那个变量,不是重新绑定。 所以本题正确。
易错点: “给引用赋值”和“让引用改绑到别处”是两回事。
判断题 3
排序算法;时间复杂度;稳定性
快速排序和归并排序的平均时间复杂度都是
𝑂
(
𝑛
log
𝑛
)
O(nlogn) ,但快速排序是不稳定的排序算法,归并排序是稳定的排序算法。
正确 正确 错误 错误
展开解析
答案:正确
排序算法 时间复杂度 稳定性
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
快速排序和归并排序的平均时间复杂度都为 O(n log n) 。 快速排序通常是不稳定排序,归并排序是稳定排序。 这两个判断都对,所以本题正确。
易错点: 稳定性考查的是相等元素的相对顺序是否保持。
判断题 4
数学函数;返回值类型;C++ 标准库
使用 math.h 或 cmath 头文件中的函数,表达式 sqrt(4) 的结果类型为 double。
正确 正确 错误 错误
展开解析
答案:正确
数学函数 返回值类型 C++ 标准库
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
sqrt 在 cmath 中返回浮点结果,表达式 sqrt(4) 的结果类型是 double。 即使参数写成整数,返回值也不是整型。 所以本题正确。
易错点: 参数是整数,不代表返回值也是整数。
判断题 5
杨辉三角;二项式定理
在杨辉三角形中,第 n 行(从0开始计数,即第 n 行有
𝑛
+
1
n+1个数)的所有数字之和等于
2
𝑛
2
n
。
正确 正确 错误 错误
展开解析
答案:正确
杨辉三角 二项式定理
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
杨辉三角第 n 行各项系数之和,等于 (1+1)^n = 2^n。 题目已经说明行号从0开始计数,因此第 n 行所有数字之和就是 2^n。 所以本题正确。
易错点: 不要把“第 n 行”与“有 n 个数”的版本混淆,题目这里是有 n+1 个数。
判断题 6
Dijkstra;复杂度比较;图的稠密与稀疏
使用二叉堆优化的Dijkstra最短路算法,在某些特殊情况下时间复杂度不如朴素实现的
𝑂
(
𝑉
2
)
O(V
2
) 。
正确 正确 错误 错误
展开解析
答案:正确
Dijkstra 复杂度比较 图的稠密与稀疏
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
朴素 Dijkstra 的复杂度是 O(V^2) ,二叉堆优化后通常是 O((V+E) logV)。 在稠密图中,E 接近 V^2,这时 O((V+E) logV) 可能比 O(V^2) 更差。 所以题目说“某些特殊情况下时间复杂度不如朴素实现”是正确的。
易错点: 堆优化不是任何情况下都更快,要看图的边数规模。
判断题 7
Catalan 数;Bell 数;组合计数
n 个不同元素依次入栈的出栈序列数与将 n 个不同元素划分成若干非空子集的方案数相等。
正确 正确 错误 错误
展开解析
答案:错误
Catalan 数 Bell 数 组合计数
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
n 个不同元素依次入栈的合法出栈序列个数是 Catalan 数。 把 n 个不同元素划分成若干非空子集的方案数是 Bell 数。 这两个数列不是同一个数列,因此不相等,所以本题错误。
易错点: 都属于计数问题,但对应的模型完全不同。
判断题 8
快速排序;最坏复杂度;随机化
快速排序在最坏情况下的时间复杂度为
𝑂
(
𝑛
log
𝑛
)
O(nlogn) ,可以通过随机化选择基准值(pivot)的方法完全避免退化。
正确 正确 错误 错误
展开解析
答案:错误
快速排序 最坏复杂度 随机化
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
快速排序最坏情况下的时间复杂度是 O(n^2) ,不是 O(n log n) 。 随机化选 pivot 只能降低退化概率,不能彻底保证永不退化。 所以题目两处说法都不对,本题错误。
易错点: “随机化能改善平均表现”不等于“能完全消除最坏情况”。
判断题 9
构造函数;析构函数;函数重载
在C++语言中,一个类可以拥有多个构造函数,也可以拥有多个析构函数。
正确 正确 错误 错误
展开解析
答案:错误
构造函数 析构函数 函数重载
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
一个类可以有多个构造函数,因为构造函数可以重载。 但析构函数不能重载,一个类只能有一个析构函数。 所以题目后半句错误,本题错误。
易错点: 构造函数能重载,析构函数不能重载,这是常见考点。
判断题 10
最长公共子序列;动态规划;空间优化
求两个序列的最长公共子序列(LCS)时,使用滚动数组优化空间后,仍然可以还原出具体的LCS序列。
正确 正确 错误 错误
展开解析
答案:错误
最长公共子序列 动态规划 空间优化
思考路径: 先抓住题目的考点,再把题干条件转成可以计算、判断或套用性质的步骤;最后用选项反查是否有常见陷阱。
分步推导
滚动数组只保留少量行或列,能算出 LCS 长度,但会丢失很多中间状态。 如果不额外保存转移信息,通常无法直接还原出完整的 LCS 序列。 所以题目中的说法不成立,本题错误。
易错点: “能求长度”和“能还原具体方案”是两个不同层次的问题。
答案速查表 单选题 1B 2B 3A 4C 5B 6C 7B 8B 9C 10C 11C 12B 13A 14C 15B
判断题 1正确 2正确 3正确 4正确 5正确 6正确 7错误 8错误 9错误 10错误
GESP8 · 2025-12-Level-8 客观题逐题讲义 · 来源:g.nuuli.com 试卷解析 · 离线课堂版