GESP 客观题评测系统

2023-12-Level-7

2023-12-Level-7

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

单选题(每题 2 分)

1 题(单选题

定义变量 double x,如果下面代码输入为 100,输出最接近()。

#include <iostream>
#include <string>
#include <cmath>
#include <vector>
using namespace std;

int main()
{
    double x;
    cin >> x;
    cout << log10(x) - log2(x) << endl;
    cout << endl;
    return 0;
}
A.
0
B.
-5
C.
-8
D.
8

正确答案B

解析详情

【答案】B

【考点】对数换底与数值估算

【解析】 输入的 100 是 x,不是题目个数。程序计算的是 log10(100)-log2(100)=2-6.64...≈-4.64,所以最接近 -5。

【易错点】 不要把 log10 和 log2 当成同一种对数来算。

2 题(单选题

对于下面动态规划方法实现的函数,以下选项中最适合表达其状态转移函数的为()。

int s[MAX_N], f[MAX_N][MAX_N];
int stone_merge(int n, int a[]) {
    for (int i = 1; i <= n; i++)
        s[i] = s[i - 1] + a[i];
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            if (i == j)
                f[i][j] = 0;
        else
            f[i][j] = MAX_F;
        for (int l = 1; l < n; l++)
            for (int i = 1; i <= n - 1; i++)
            int j = i + 1;
        for (int k = i; k < j; k++)
            f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j] + s[j] - s[i - 1]);
    }
    return f[1][n];
}
A.
f(i,j)=minik<j(f(i,j),f(i,k)+f(k+1,j)+s(j)s(i1))f(i,j) = \min_{i \leq k < j} (f(i,j), f(i,k) + f(k + 1,j) + s(j) - s(i - 1))
B.
f(i,j)=minik<j(f(i,j),f(i,k)+f(k+1,j)+k=ija(k))f(i,j) = \min_{i \leq k < j} (f(i,j), f(i,k) + f(k + 1,j) + \sum_{k=i}^{j} a(k))
C.
f(i,j)=minikj(f(i,k)+f(k+1,j)+k=ij+1a(k))f(i,j) = \min_{i \leq k \leq j} (f(i,k) + f(k + 1,j) + \sum_{k=i}^{j+1} a(k))
D.
f(i,j)=minik<j(f(i,k)+f(k+1,j))+k=ija(k)f(i,j) = \min_{i \leq k < j} (f(i,k) + f(k + 1,j)) + \sum_{k=i}^{j} a(k)

正确答案D

解析详情

【答案】D

【考点】区间动态规划

【解析】 f[i][j] 表示把区间 [i,j] 合并成一堆的最小代价,枚举断点 k 后有 f[i][j]=min(f[i][k]+f[k+1][j])+sum(i,j)。代码中的 s[j]-s[i-1] 正是区间和,所以 D 与程序一致。

【易错点】 min 里应比较不同断点的结果,区间总代价要放在 min 外面统一加。

3 题(单选题

下面代码可以用来求最长上升子序列(LIS)的长度,如果输入是:5 1 7 3 5 9,则输出是()。

int a[2023], f[2023];
int main()
{
    int n, i, j, ans = -1;
    cin >> n;
    for (i = 1; i <= n; i++) {
        cin >> a[i];
        f[i] = 1;
    }
    for (i = 1; i <= n; i++) {
        for (j = 1; j < i; j++) {
            if (a[j] < a[i]) {
                f[i] = max(f[i], f[j] + 1);
            }
        }
    }
    for (i = 1; i <= n; i++) {
        ans = max(ans, f[i]);
        cout << f[i] << " ";
    }
    cout << ans << endl;
    return 0;
}
A.
9 7 5 1 1 9
B.
1 2 2 3 4 4
C.
1 3 5 7 9 9
D.
1 1 1 1 1

正确答案B

解析详情

【答案】B

【考点】最长上升子序列 DP

【解析】 首个 5 是 n,序列实际为 1,7,3,5,9。对应 f 依次是 1,2,2,3,4,最后 ans=4,所以输出为 1 2 2 3 4 4。

【易错点】 容易把开头的 5 误当成序列元素,导致整题多算一位。

4 题(单选题

C++ 语言中,下列关于关键字 static 的描述不正确的是()。

A.
可以修饰类的成员函数。
B.
常量静态成员可以在类外进行初始化。
C.
若 a 是类 A 常量静态成员,则 a 的地址都可以访问且唯一。
D.
静态全局对象一定在 main 函数调用前完成初始化,执行完 main 函数后被析构。

正确答案C

解析详情

【答案】C

【考点】C++ static 成员

【解析】 static 成员函数确实存在,静态常量成员也可以在类外定义;静态存储期对象通常在 main 前初始化、main 结束后析构。C 错在“地址都可以访问”这一句,能否访问还受 public/private 限制。

【易错点】 静态成员“只有一份”不等于“任何位置都能访问”。

5 题(单选题

G 是一个非连通无向图,共有 28 条边,则该图至少有()个顶点。

A.
6
B.
7
C.
8
D.
9

正确答案D

解析详情

【答案】D

【考点】无向图边数上界

【解析】 8 个顶点的完全图边数是 8×7÷2=28,但完全图一定连通,不满足“非连通”。要保留 28 条边又非连通,只能让 8 个点构成完全图,再加 1 个孤立点,因此至少 9 个顶点。

【易错点】 先看边数上界后,还要继续检查“非连通”这个附加条件。

6 题(单选题

哈希表长31,按照下面的程序依次输入 4 17 28 30 4,则最后的 4 存入哪个位置?()

#include <iostream>
#include <string>
#include <cmath>
#include <vector>

using namespace std;

const int N=31;
int htab[N], flag[N];
int main()
{
    int n, x, i, j, k;
    
        cin >> n;
        for (i=0; i<n; i++) {
            cin >> x;
            k=x%13;
            while (flag[k]) k = (k+1)%13;
            htab[k]=x;
            flag[k]=1;
        }
        for (i=0; i<N; i++)
            cout << htab[i] << " ";
        cout << endl;
    
    return 0;
}
A.
3
B.
4
C.
5
D.
6

正确答案D

解析详情

【答案】D

【考点】开放定址哈希

【解析】 首个 4 是输入个数 n,真正插入的是 17,28,30,4。它们的位置依次为 17→4,28→2,30 由 4 冲突后到 5,最后 4 从 4 开始线性探测,4、5 已占,存到 6。

【易错点】 不要把题目最前面的 4 也当成待插入的数据。

7 题(单选题

某二叉树 T 的先序遍历序列为:{A B D F C E  G H}\{A \text{ B } D \text{ F } C \text{ E } \text{ G } H\},中序遍历序列为:{B F D A G E H C}\{B \text{ F } D \text{ A } G \text{ E } H \text{ C}\},则下列说法中正确的是()。

A.
T 的度为 1
B.
T 的高为 4
C.
T 有 4 个叶节点
D.
以上说法都不对

正确答案B

解析详情

【答案】B

【考点】由先序和中序还原二叉树

【解析】 根结点是 A。由中序可还原出左侧链 B→D→F,右子树为 C,其左子树根为 E,E 的左右孩子分别是 G、H。最长路径长度为 A-B-D-F 或 A-C-E-G,共 4 层,所以 B 正确。

【易错点】 树的高度要按还原后的层数判断,不能只靠结点个数猜。

8 题(单选题

下面代码段可以求两个字符串 s1 和 s2 的最长公共子串(LCS),下列相关描述不正确的是()。

while (cin >> s1 >> s2)
{
    memset(dp, 0, sizeof(dp));
    int n1 = strlen(s1), n2 = strlen(s2);
    for (int i = 1; i <= n1; ++i)
        for (int j = 1; j <= n2; ++j)
            if (s1[i - 1] == s2[j - 1])
                dp[i][j] = dp[i - 1][j - 1] + 1;
            else
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
    cout << dp[n1][n2] << endl;
}
A.
代码的时间复杂度为O(n2)O(n^2)
B.
代码的空间复杂度为O(n2)O(n^2)
C.
空间复杂度已经最优
D.
采用了动态规划求解

正确答案C

解析详情

【答案】C

【考点】最长公共子序列与空间优化

【解析】 这段转移式 dp[i][j]=max(dp[i-1][j],dp[i][j-1]) 实际求的是最长公共子序列,不是子串;其时间和空间复杂度都是 O(n1×n2)。二维 DP 可以压成两行甚至一行,因此“空间复杂度已经最优”不成立。

【易错点】 看到 LCS 不要自动理解成子串,先看转移方程。

9 题(单选题

图的广度优先搜索中既要维护一个标志数组标志已访问的图的特点,还需哪种结构存放结点以实现遍历?()

A.
双向栈
B.
队列
C.
哈希表
D.

正确答案B

解析详情

【答案】B

【考点】广度优先搜索

【解析】 BFS 按“先发现先扩展”的层次顺序访问结点,待访问结点必须按先进先出管理,所以要配合队列使用。

【易错点】 DFS 常配栈或递归,BFS 则对应队列。

10 题(单选题

对关键字序列 {44, 36, 23, 35, 52, 73, 90, 58} 建立哈希表,哈希函数为 h(k)=k%7,执行下面的 Insert 函数,则等概率情况下的平均成功查找长度(即查找成功时的关键字比较次数的均值)为( )。

#include <iostream>
#include <string>
#include <cmath>
#include <vector>

using namespace std;

typedef struct Node{
    int data;
    struct Node *next;
} Node;

Node* hTab[7];
int key[] = {44, 36, 23, 35, 52, 73, 90, 58, 0};

void Insert()
{
    int i, j;
    Node *x;
    for (i = 0; key[i]; i++) {
        j = key[i] % 7;
        x = new Node;
        x->data = key[i];
        x->next = hTab[j];
        hTab[j] = x;
    }
}
A.
7/8
B.
1
C.
1.5
D.
2

正确答案C

解析详情

【答案】C

【考点】链地址法哈希查找

【解析】 按 key%7 分桶后得到:0 桶 {35},1 桶 {36},2 桶头插后为 {58,23,44},3 桶为 {73,52},6 桶为 {90}。成功查找比较次数分别是 1,1,1,2,3,1,2,1,总和 12,平均 12/8=1.5。

【易错点】 头插法会把后插入元素放到链表前面,比较次数顺序会反过来。

11 题(单选题

学生在读期间所上的某些课程中需要先上其他的课程,所有课程和课程间的先修关系构成一个有向图 G,有向边 <U,V> 表示课程 U 是课程 V 的先修课,则要找到某门课程 C 的全部先修课下面哪种方法不可行?()

A.
BFS搜索
B.
DFS搜索
C.
DFS+BFS
D.
动态规划

正确答案D

解析详情

【答案】D

【考点】有向图可达性

【解析】 要找课程 C 的全部先修课,本质是找所有能到达 C 的顶点;把边反向后做 BFS 或 DFS 都可以。动态规划不直接解决一般有向图的可达性枚举,因此 D 不可行。

【易错点】 “先修课集合”是图遍历问题,不是最优值问题。

12 题(单选题

一棵完全二叉树有 2023 个结点,则叶结点有多少个?()

A.
1024
B.
1013
C.
1012
D.
1011

正确答案C

解析详情

【答案】C

【考点】完全二叉树叶子结点个数

【解析】 完全二叉树编号为 1 到 n 时,1 到 ⌊n/2⌋ 都是非叶子,叶子数为 n-⌊n/2⌋=⌈n/2⌉。n=2023 时叶子数为 2023-1011=1012。

【易错点】 奇数个结点时,叶子数是向上取整,不是向下取整。

13 题(单选题

用下面的邻接表结构保存一个有向图 G,InfoType 和 VertexType 是定义好的类。设 G 有 n 个顶点、e 条弧,则求图 G 中某个顶点 u (其顶点序号为 k)的度的算法复杂度是()。

typedef struct ArcNode{
    int     adjvex; // 该弧所指向的顶点的位置
    struct ArcNode *nextarc; // 指向下一条弧的指针
    InfoType *info; // 该弧相关信息的指针
} ArcNode;
typedef struct VNode{
    VertexType data; // 顶点信息
    ArcNode *firstarc; // 指向第一条依附该顶点的弧
} VNode, AdjList[MAX_VERTEX_NUM];
typedef struct{
    AdjList vertices;
    int     vexnum, arcnum;
    int     kind; // 图的种类标志
} ALGraph;
A.
O(n)O(n)
B.
O(e)O(e)
C.
O(n+e)O(n+e)
D.
O(n+2e)O(n+2*e)

正确答案B

解析详情

【答案】B

【考点】邻接表复杂度分析

【解析】 在有向图的邻接表中,u 的出度可顺着第 k 个表头统计,但入度必须扫描所有顶点的弧链才能知道有多少弧指向 u。总工作量由扫描全部弧主导,因此是 O(e)。

【易错点】 有向图的“度”是入度加出度,不能只看顶点自己的链表。

14 题(单选题

给定一个简单有向图 G,判断其中是否存在环路的下列说法哪个最准确?()

A.
BFS更快
B.
DFS更快
C.
BFS和DFS一样快
D.
不确定

正确答案D

解析详情

【答案】D

【考点】有向图判环

【解析】 DFS 可以用回边判环,BFS 也常借助拓扑排序判环,二者都能在线性复杂度内完成。题目没有限定图规模、存储方式和实现细节,无法据此断定谁一定更快,所以选“不确定”。

【易错点】 复杂度同为 O(n+e) 时,不能简单得出“谁更快”的绝对结论。

15 题(单选题

从顶点 v1 开始遍历下图 G 得到顶点访问序列,在下面所给的 4 个序列中符合广度优先的序列有几个?( ) {v1 v2 v3 v4 v5},{v1 v2 v4 v3 v5},{v1 v4 v2 v3 v5},{v1 v2 v4 v5 v3}

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

正确答案B

解析详情

【答案】B

【考点】BFS 访问序列

【解析】 需结合图片确认:从 v1 出发时,v2 和 v4 属于第一层,v3 和 v5 在下一层。BFS 必须先访问完同层结点,所以 {v1,v2,v3,v4,v5} 不可能出现,其余 3 个序列可由不同邻接访问顺序得到。

【易错点】 BFS 序列允许同层内部交换,但不允许下一层结点跑到上一层前面。

判断题(每题 2 分)

1 题(判断题

小杨这学期准备参加GESP的7级考试,其中有关于三角函数的内容,他能够通过下面的代码找到结束循环的角度值。()

int main()
{
    double x;
    do {
        cin >> x;
        x = x / 180 * 3.14;
    } while (int(sin(x) * sin(x) + cos(x) * cos(x)) == 1);
    cout << " // " << sin(x) << " " << cos(x);
    cout << endl;
    return 0;
}

正确答案正确

解析详情

【答案】正确

【考点】浮点误差与三角恒等式

【解析】 理论上 sin²x+cos²x=1,但程序把角度换成弧度时用了 3.14,不是精确的 π。某些输入会使表达式略小于 1,int 截断后变成 0,从而跳出循环,所以确实可能找到结束循环的角度值。

【易错点】 浮点计算里“理论恒等于 1”不代表程序里一定仍然精确等于 1。

2 题(判断题

小杨在开发画笔刷小程序(applet),操作之一是选中黄颜色,然后在下面的左图的中间区域双击后,就变成了右图。这个操作可以用图的泛洪算法来实现。()

左图右图

正确答案正确

解析详情

【答案】正确

【考点】泛洪填充

【解析】 双击中间区域后,程序会从起点向四周扩展,把与起点连通且颜色相同的区域整体替换成目标颜色,这正是 flood fill 的典型应用。

【易错点】 泛洪算法处理的是“连通区域”,不是把整张图里同色像素全部一起改掉。

3 题(判断题

假设一棵完全二叉树共有 N 个节点,则树的深度为log(N)+1\log(N) + 1。()

正确答案错误

解析详情

【答案】错误

【考点】完全二叉树深度公式

【解析】 完全二叉树有 N 个结点时,深度应为 ⌊log2N⌋+1。题目直接写成 log(N)+1,既缺少以 2 为底,也少了向下取整,因此不正确。

【易错点】 树高公式里最容易漏掉对数底数和取整符号。

4 题(判断题

给定一个数字序列 A1, A2, A3, ..., An,要求 i 和 j (1<=i<=j<=n),使 A1+...+Aj 最大,可以使用动态规划方法来求解。()

正确答案正确

解析详情

【答案】正确

【考点】动态规划求最优子段

【解析】 无论按题面理解为前缀和最大,还是常见的区间和最优问题,都可以把“以某位置结尾的最优值”作为状态递推。动态规划能在线性时间内完成求解。

【易错点】 这类最优连续和问题常见做法就是维护“截至当前位置的最优状态”。

5 题(判断题

若变量 x 为 double 类型正数,则log(exp(x))>log10(x)\log(\exp(x)) > \log_{10}(x)。()

正确答案正确

解析详情

【答案】正确

【考点】对数与指数函数

【解析】 对正数 x 有 log(exp(x))=x。又因为 x>0 时恒有 x>log10(x),例如 0<x<1 时右边为负,x≥1 时 x 的增长也远快于十进对数,所以不等式成立。

【易错点】 ln(e^x)=x 是基本恒等式,不要把不同底数对数混淆。

6 题(判断题

简单有向图有 n 个顶点和 e 条弧,可以用邻接矩阵或邻接表来存储,二者求节点 u 的度的时间复杂度一样。()

正确答案错误

解析详情

【答案】错误

【考点】邻接矩阵与邻接表

【解析】 邻接矩阵求某点的度通常要扫描整行甚至整列,复杂度是 O(n)。邻接表中出度可按链表统计,入度若无额外数组往往要扫描全部弧,复杂度更接近 O(e),二者并不一样。

【易错点】 存储结构不同,同一操作的复杂度也可能完全不同。

7 题(判断题

某个哈希表键值 x 为整数,为其定义哈希函数 H(x)=x%p ,则 p 选择素数时不会产生冲突。()

正确答案错误

解析详情

【答案】错误

【考点】哈希冲突

【解析】 把模数 p 取成素数只能改善分布,不能保证无冲突。只要两个整数相差 p 的倍数,例如 1 和 p+1,就会得到同一个哈希值。

【易错点】 “冲突更少”不等于“绝对不会冲突”。

8 题(判断题

动态规划只要推导出状态转移方程,就可以写出递归程序来求出最优解。()

正确答案错误

解析详情

【答案】错误

【考点】动态规划实现条件

【解析】 有状态转移方程只是第一步,还必须有明确的边界、计算顺序或记忆化机制。若直接写成普通递归而不记忆,往往会出现大量重复计算,不能视为有效的动态规划实现。

【易错点】 动态规划的关键不只是方程,还包括如何避免重复子问题。

9 题(判断题

广度优先搜索(BFS)能够判断图是否连通。()

正确答案正确

解析详情

【答案】正确

【考点】图的连通性判断

【解析】 从任意一个起点做 BFS,若遍历结束后所有顶点都被访问到,则图连通;若仍有未访问顶点,则图不连通。因此 BFS 可以用来判断连通性。

【易错点】 判断连通性看的是一次遍历后是否覆盖所有顶点。

10 题(判断题

在C++中,如果定义了构造函数,则创建对象时先执行完缺省的构造函数,再执行这个定义的构造函数。()

正确答案错误

解析详情

【答案】错误

【考点】C++ 构造函数调用顺序

【解析】 创建对象时会直接调用与实参匹配的构造函数,并不会先执行一遍缺省构造函数再执行自定义构造函数。只有成员对象或基类子对象才会按各自规则先构造。

【易错点】 “先构造成员和基类”不等于“先调用默认构造再调用目标构造”。