试卷解析 · 理解每一步
2025-09-Level-8
2025-09-Level-8
试卷解析总览,可直接查看每题答案与解析。
第 1 题(单选题,2 分)
小杨想点一杯奶茶外卖,但还差5元起送。于是,小杨决定点一些小料。可选的小料包括:珍珠1元、椰果2元、奶冻3元、奶盖4元。每种小料最多点1份。请问共有多少种满足起送条件的点小料方案?()。
正确答案C
解析详情
四种小料各选或不选,共 个子集。
金额不足 5 的有空集、四种单料、{1,2}、{1,3},共 7 种。因此达到起送金额的有 种,选 C。
第 2 题(单选题,2 分)
小杨和小刘是好朋友,她们在逛商场时发现新设置的大头贴自拍机,于是决定一起拍一组照片。一组照片包括4张,这4张照片没有顺序区分。拍每张照片时,可以选择有相框或无相框、两人可以分别选择有头饰或无头饰、还可以从2种位置(小杨在左,或小刘在左)中选出一种。她们不希望一组照片中出现完全相同的相框、头饰、位置的组合。请问一组照片共有多少种不同的方案?()。
正确答案A
解析详情
单张照片有相框、两人的头饰、左右位置四项二选一,共 种。
从中选 4 张不同照片且不分顺序,有 种,选 A。
第 3 题(单选题,2 分)
下列关于C++类的说法,错误的是()。
正确答案C
解析详情
含纯虚函数的类不能直接实例化,但仍能包含成员变量、构造函数和普通方法。
例如抽象图形类可保存颜色,并把面积计算声明为纯虚函数。因此 C 错误。
第 4 题(单选题,2 分)
下列关于树和图的说法,错误的是()。
正确答案B
解析详情
考虑两个顶点和唯一边 1→2:它本身就是一棵有向树,却不能从 2 到达 1。
因此存在有向生成树不保证强连通,B 错误。
第 5 题(单选题,2 分)
一对夫妻生男生女的概率相同。这对夫妻希望儿女双全。请问这对夫妻生下三个孩子时,实现儿女双全的概率是多少?( )。
正确答案C
解析详情
按三次性别独立、男女各半的假设,共 种等概率顺序。
未实现儿女双全的只有全男和全女,因此概率为 ,选 C。
第 6 题(单选题,2 分)
二项式的展开式中项的系数是()。
正确答案D
解析详情
六个 (x+y) 相乘,要得到 ,需从 6 个因子中选 2 个取 x,余下取 y。
系数为 ,选 D。
第 7 题(单选题,2 分)
对一个包含 V 个顶点、E 条边的图,执行广度优先搜索,其最优时间复杂度是()。
正确答案B
解析详情
邻接表实现完整 BFS 时,每个顶点入队一次,每条邻接项扫描一次。
两部分合计为 ,选 B;无向边有两个邻接项,只增加常数倍。
第 8 题(单选题,2 分)
以下关于贪心法和动态规划的说法中,错误的是()。
正确答案A
解析详情
多阶段决策并不自动保证可得到有效的 DP,还需合适的状态、最优子结构以及可接受的状态和转移规模。
有些问题的状态空间可能指数增长,不能泛称“大部分”都能有效解决,因此按题目口径选 A。
第 9 题(单选题,2 分)
下面程序的输出为()。
#include <iostream>
using namespace std;
int main() {
int N = 15, cnt = 0;
for (int x = 1; x + x + x <= N; x++)
for (int y = x; x + y + y <= N; y++)
for (int z = y; x + y + z <= N; z++)
cnt++;
cout << cnt << endl;
return 0;
}正确答案B
解析详情
枚举条件为 且 。固定 x、y 时,z 从 y 到 15−x−y,共 16−x−2y 个。
x=1、2、3、4、5 时分别贡献 49、30、16、6、1 个,合计 102,选 B。
第 10 题(单选题,2 分)
下面程序的时间复杂度为()。
int primes[MAXP], num = 0;
bool isPrime[MAXN] = {false};
void sieve() {
for (int n = 2; n <= MAXN; n++) {
if (!isPrime[n])
primes[num++] = n;
for (int i = 0; i < num && n * primes[i] <= MAXN; i++) {
isPrime[n * primes[i]] = true;
if (n % primes[i] == 0)
break;
}
}
}正确答案C
解析详情
这段代码是欧拉筛。关键性质是每个合数只会被它的最小质因子筛掉一次,所以内层循环的总执行次数对所有 n 累加后仍是线性的。
因此整体时间复杂度是 O(n),对应 C。
第 11 题(单选题,2 分)
下列Dijkstra算法,假设图 graph 中顶点数 v、边数 e,则程序的时间复杂度为()。
typedef struct Edge {
int in, out; // 从下标in顶点到下标out顶点的边
int len; // 边长度
struct Edge* next;
} Edge;
// v:顶点个数,graph:出边邻接表,start:起点下标,dis:输出每个顶点的最短距离
void dijkstra(int v, Edge* graph[], int start, int* dis) {
const int MAX_DIS = 0x7fffff;
for (int i = 0; i < v; i++) {
dis[i] = MAX_DIS;
}
dis[start] = 0;
int* visited = new int[v];
for (int i = 0; i < v; i++) {
visited[i] = 0;
}
visited[start] = 1;
for (int t = 0;; t++) {
int min = MAX_DIS, minv = -1;
for (int i = 0; i < v; i++) {
if (visited[i] == 0 && min > dis[i]) {
min = dis[i];
minv = i;
}
}
if (minv < 0) {
break;
}
visited[minv] = 1;
for (Edge* e = graph[minv]; e != NULL; e = e->next) {
if (dis[e->out] > e->len) {
dis[e->out] = e->len;
}
}
}
delete[] visited;
}
正确答案A
解析详情
这份程序每轮都用一个长度为 v 的线性扫描找当前未访问点中距离最小的顶点,这一步要做 v 次,所以代价是 O(v^2)。
遍历邻接表的总代价是 O(e),合起来是 O(v^2+e)。因为简单图中 e≤v^2,最终记为 O(v^2),选 A。
第 12 题(单选题,2 分)
下面 count_triple 函数的时间复杂度为()。
int gcd(int m, int n) {
if (m == 0) return n;
return gcd(n % m, m);
}
int count_triple(int n) {
int cnt = 0;
for (int v = 1; v * v * 4 <= n; v++)
for (int u = v + 1; u * (u + v) * 2 <= n; u += 2)
{
if (gcd(u, v) == 1) {
int a = u * u - v * v;
int b = u * v * 2;
int c = u * u + v * v;
cnt += n / (a + b + c);
}
return cnt;
}
}
}正确答案D
解析详情
按题目意图分析,外层枚举 (u,v) 的总次数与 n 同阶;其中每次最重的操作是 gcd(u,v),欧几里得算法复杂度为 O(log n)。
因此总时间复杂度为 O(n log n),选 D。
第 13 题(单选题,2 分)
下面 merge_sort 函数试图实现归并排序算法,横线处应该填入的是()。
#include <vector>
using namespace std;
void merge_sort(vector<int> & arr, int left, int right) {
if (right - left <= 1)
return;
int mid = (left + right) / 2;
merge_sort(____); // 在此处填入选项
merge_sort(____); // 在此处填入选项
vector<int> temp(right - left);
int i = left, j = mid, k = 0;
while (i < mid && j < right)
if (arr[i] <= arr[j])
temp[k++] = arr[i++];
else
temp[k++] = arr[j++];
while (i < mid)
temp[k++] = arr[i++];
while (j < right)
temp[k++] = arr[j++];
for (i = left, k = 0; i < right; ++i, ++k)
arr[i] = temp[k];
}正确答案A
解析详情
待排序区间是 [left,right),长度为 right−left,右端不包含在内。
以 mid 为界,两个子区间应是 [left,mid) 和 [mid,right),无遗漏也无重叠,所以选 A;后续 i=left、j=mid 的合并起点也与此一致。
第 14 题(单选题,2 分)
下面Prim算法程序中,横线处应该填入的是()。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int prim(vector<vector<int>> & graph, int n) {
vector<int> key(n, INT_MAX);
vector<int> parent(n, -1);
key[0] = 0;
for (int i = 0; i < n; i++) {
int u = min_element(key.begin(), key.end()) - key.begin();
if (key[u] == INT_MAX)
break;
for (int v = 0; v < n; v++) {
if (_____) { // 在此处填入选项
key[v] = graph[u][v];
parent[v] = u;
}
}
int sum = 0;
for (int i = 0; i < n; i++) {
if (parent[i] != -1) {
cout << "Edge: " << parent[i] << " - " << i << " Weight: " << key[i] << endl;
sum += key[i];
}
}
return sum;
}
int main() {
int n, m;
cin >> n >> m;
vector<vector<int>> graph(n, vector<int>(n, 0));
for (int i = 0; i < m; i++) {
int u, v, w;
cin >> u >> v >> w;
graph[u][v] = w;
graph[v][u] = w;
}
int result = prim(graph, n);
cout << "Total weight of the minimum spanning tree: " << result << endl;
return 0;
}
}正确答案D
解析详情
邻接矩阵里 0 表示无边,因此候选边必须满足 graph[u][v] != 0。同时只有当当前边权更小,即 key[v] > graph[u][v] 时,才需要更新最小连接代价。
因此应填 graph[u][v] != 0 && key[v] > graph[u][v],选 D。
第 15 题(单选题,2 分)
下面的程序使用出边邻接表表达的带权无向图,则从顶点0到顶点3的最短距离为()。
#include <vector>
using namespace std;
class Edge {
public:
int dest;
int weight;
Edge(int d, int w) : dest(d), weight(w) {}
};
class Graph {
private:
int num_vertex;
vector<vector<Edge>> vve;
public:
Graph(int v) : num_vertex(v), vve(v) {}
void addEdge(int s, int d, int w) {
vve[s].emplace_back(d, w);
vve[d].emplace_back(s, w)
}
};
int main() {
Graph g(4);
g.addEdge(0, 1, 8);
g.addEdge(0, 2, 5);
g.addEdge(1, 2, 1);
g.addEdge(1, 3, 3);
g.addEdge(2, 3, 7);
return 0;
}
}正确答案D
解析详情
由 addEdge 的两个方向可知这里是无向图。0→1→3 为 8+3=11,0→2→3 为 5+7=12。
走 0→2→1→3 的长度为 ,比其他简单路径更短,选 D。正权边上的绕圈不会改善结果。
判断题
第 1 题(判断题,2 分)
C++语言中,表达式 '9' ^ 3 的结果值为 '999'。
正确答案错误
解析详情
^ 是按位异或。在常见 ASCII 下,'9' 为 57,二进制 111001;3 为 000011。
异或得到 111010,即整数 58,不是所谓的 '999',因此错误。
第 2 题(判断题,2 分)
下列C++语言代码,能够安全地输出 arr[5] 的值。
int n = 5;
int arr[n] = {1, 2, 3};
std::cout << arr[5];正确答案错误
解析详情
长度为 5 的数组合法下标为 0 到 4,arr[5] 是越界访问,不能安全输出。
只给前三个初值会使其余合法元素补 0,并不会多分配第六个元素。严格标准 C++ 还不支持题中以普通运行期 n 声明内置变长数组。
第 3 题(判断题,2 分)
对n个元素的数组进行排序,最差情况的时间复杂度为。
正确答案错误
解析详情
不同排序算法有不同最坏界,例如归并排序、堆排序最坏为 ,标准冒泡排序最坏为 。
所以不能只说“排序”就统一指定平方级的紧确复杂度,判断错误。
第 4 题(判断题,2 分)
有4个红球、3个蓝球和2个绿球排成一排(相同色球视为完全相同),则不同的排列方案数为1260种。
正确答案正确
解析详情
先从 9 个位置选 4 个放红球,再从余下 5 个选 3 个放蓝球,最后两个放绿球。
方案数为 ,故正确。
第 5 题(判断题,2 分)
使用 math.h 或 cmath 头文件中的函数,对于 int 类型的变量 x,表达式 fabs(x) 和 sqrt(x * x) 的结果总是近似相等的。
正确答案错误
解析详情
数学上 ,但 x*x 先进行 int 乘法,再传给 sqrt。
在 32 位 int 下,x=50000 的平方超过最大值,发生有符号溢出;fabs(x) 不经历这个整数平方,所以两式不能保证总是近似相等。
第 6 题(判断题,2 分)
运算符重载是C++语言静态多态的一种典型体现,而使用C语言则无法实现运算符重载。
正确答案正确
解析详情
C++ 可通过 operator 函数为自定义类型定义运算,并在编译期按操作数类型选择实现,这是静态多态。
C 没有提供自定义运算符重载语法,只能以普通函数等方式实现类似计算,所以判断正确。
第 7 题(判断题,2 分)
存在一个简单无向图满足:顶点数为6,边数为8,6个顶点的度数分别为3、3、3、3、2、2。
正确答案正确
解析详情
先用六个顶点构成一个环,共 6 条边,每个顶点度数为 2。
再添加弦 1—3 和 2—4,四个端点度数各增加 1,最终为 3、3、3、3、2、2,边数为 8。因此所求简单图存在。
第 8 题(判断题,2 分)
已知两个 double 类型的变量 r 和 theta 分别表示一个扇形的圆半径及圆心角(弧度),则扇形的周长可以通过表达式(2 + theta) * r 求得。
正确答案正确
解析详情
圆心角以弧度计时,弧长为 rθ。扇形还包含两条长度为 r 的半径边界。
所以周长为 ,题目正确。
第 9 题(判断题,2 分)
Dijkstra算法的时间复杂度为,其中 V 为图中顶点的数量。
正确答案错误
解析详情
朴素实现每轮扫描顶点选最小距离,可得到 。
邻接表配合二叉堆的常见实现则为 ,因此不说明实现就固定写为 O(V²),按题目口径判断错误。
第 10 题(判断题,2 分)
从32名学生中选出2人分别担任男生班长和女生班长(男生班长必须是男生,女生班长必须是女生),则共有种不同的选法。
正确答案错误
解析详情
设男生 m 人、女生 32−m 人,两个职务分别从对应性别中选择,实际方案数为 。
例如男女各 16 人时有 256 种,而 ,所以题中公式错误。