GESP202603 C++四级真题“保姆级”详细题解

四季读书网 1 0
GESP202603 C++四级真题“保姆级”详细题解
GESP202603 C++四级真题“保姆级”详细题解 第1张

我们七个全国信竞家长群都满人了!我们的平台已经得到了广大家长的认可和赞赏。

现在推出第八个群,扫码添加老师邀请进群:

GESP202603 C++四级真题“保姆级”详细题解 第2张

入群免费共享信息学竞赛圈资源、竞赛解析与讲解等。

GESP真题免费在线评测:course.coderlands.com

GESP202603 C++四级真题“保姆级”详细题解 第3张

GESP 202603 四级

单选题

第 1 题

执行下面程序后,输出为( )。

intf(int x = 2){return x * 3;}intmain(){cout << f() << " " << f(4);}
  • A. 2 12
  • B. 6 12
  • C. 6 4
  • D. 12 6

B

调用 f() 时使用默认参数 x = 2,返回 2 * 3 = 6;调用 f(4) 时返回 4 * 3 = 12,所以输出为 6 12

第 2 题

执行下面代码后,输出为( )。

intmain(){int a = 5;int* p = &a;int** q = &p;    **q += 7;cout << a << " " << *p;}
  • A. 5 5
  • B. 12 12
  • C. 12 5
  • D. 5 12

B

q 指向 p*q 就是 p**q 就是变量 a 本身。执行 **q += 7 后,a 变成 12,而 *p 访问的也是同一个变量,所以输出 12 12

第 3 题

已知:

int a[3][4] = {    {1234},    {5678},    {9101112}};int (*p)[4] = a;

则表达式 *(*(p + 2) + 1) 的值为( )。

  • A. 6
  • B. 10
  • C. 9
  • D. 11

B

p + 2 指向第 3 行,也就是 {9, 10, 11, 12}*(p + 2) 表示这一行首元素地址;再加 1 指向该行第 2 个元素 10,最后取值得到 10

第 4 题

执行下面程序后,输出为( )。

voidfun(int a, int &b, int *c){    a += 1;    b += 2;    *c += 3;}intmain(){int x = 1, y = 1, z = 1;    fun(x, y, &z);cout << x << " " << y << " " << z;}
  • A. 2 3 4
  • B. 1 3 4
  • C. 2 1 4
  • D. 1 1 1

B

参数 a 是值传递,只修改副本,不影响 xb 是引用,会把 y 改成 3c 是指针,*c += 3 会把 z 改成 4。所以输出 1 3 4

第 5 题

执行下面程序后输出为( )。

int x = 3;voidf(int& x){    x += 2;}intmain(){int x = 10;    f(x);cout << x << " " << ::x;}
  • A. 12 3
  • B. 10 5
  • C. 12 5
  • D. 10 3

A

main 中的局部变量 x 初值为 10,传引用后被改成 12::x 表示全局变量,仍然是 3,所以输出 12 3

第 6 题

下列关于结构体初始化的写法,正确的是( )。

  • A.

    structPoint {int x, y; };Point p = (12);
  • B.

    structPoint {int x, y; };Point p = {12};
  • C.

    structPoint {int x, y; };Point p = new Point(12);
  • D.

    structPoint {int x, y; };Point p = <12>;

B

普通结构体对象可以使用花括号列表初始化,如 Point p = {1, 2};。其余几种写法都不符合这里的语法要求。

第 7 题

执行下面代码后输出为( )。

structS {int a; int b; };voidg(S s){ s.a += 10; }voidh(S& s){ s.b += 10; }intmain(){    S s{12};    g(s);    h(s);cout << s.a << " " << s.b;}
  • A. 11 12
  • B. 1 12
  • C. 11 2
  • D. 1 2

B

g 是值传递,只改了副本;h 是引用传递,会把原对象中的 b 改为 12。所以最终 a 仍为 1b 为 12

第 8 题

关于递推算法的描述,正确的是( )。

  • A. 递推表现为函数自己调用自己
  • B. 递推从已知初值出发,利用递推关系逐步推出后续结果
  • C. 递推只能用于指数复杂度问题
  • D. 递推一定需要回溯

B

递推的核心是“已知前面的结果,按关系式一步步推出后面的结果”。A 说的是递归,C 和 D 都不正确。

第 9 题

执行 climb(6) 的返回值为( )。

intclimb(int n){if (n <= 2return n;int a = 1, b = 2, c = 0;for (int i = 3; i <= n; i++) {        c = a + b;        a = b;        b = c;    }return c;}
  • A. 8
  • B. 13
  • C. 5
  • D. 10

B

递推过程为:

  • climb(1)=1
  • climb(2)=2
  • climb(3)=3
  • climb(4)=5
  • climb(5)=8
  • climb(6)=13

因此返回 13

第 10 题

某排序算法对如下数据排序(按 score 升序),则下面关于该排序算法稳定性的描述中,说法正确的是( )。

初始:(90,'A'), (90,'B'), (80,'C'), (90,'D')

排序后:(80,'C'), (90,'A'), (90,'B'), (90,'D')

  • A. 不稳定,因为出现了相同分数
  • B. 稳定,因为相同 score 的相对顺序保持为 A 在 B 前、B 在 D 前
  • C. 不稳定,因为 C 跑到前面了
  • D. 无法判断

B

判断稳定性要看“关键字相等的元素相对顺序是否保持不变”。这里 score = 90 的三个元素仍然保持 A、B、D 的先后顺序,因此该排序是稳定的。

第 11 题

下面代码试图把数组按升序进行“插入排序”,横线处应填写( )。

voidins(int a[], int n){for (int i = 1; i < n; i++) {int key = a[i];int j = i - 1;while (j >= 0 && __________) {            a[j + 1] = a[j];            j--;        }        a[j + 1] = key;    }}
  • A. a[j] < key
  • B. a[j] > key
  • C. a[j+1] > key
  • D. a[j] == key

B

插入排序做升序时,需要把所有比 key 大的元素向后挪动,因此条件应为 a[j] > key

第 12 题

下列代码段的时间复杂度为( )。

int cnt = 0;for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {if ((i + j) % 3 == 0) cnt++;    }}
  • A. 
  • B. 
  • C. 
  • D. 

C

两层循环都各执行约 n 次,内部判断是常数时间,因此总时间复杂度为 

第 13 题

下面哪种方式不能实现将字符串 Welcome to 2026! 输出重定向到文件 log.txt( )。

  • A.

    freopen("log.txt""w"stdout);cout << "Welcome to 2026!" << endl;fclose(stdout);
  • B.

    std::ofstream outFile("log.txt");cout << "Welcome to 2026!" << endl;outFile.close();
  • C.

    ofstream log_file("log.txt");streambuf* org_cout = cout.rdbuf();cout.rdbuf(log_file.rdbuf());cout << "Welcome to 2026!" << endl;cout.rdbuf(org_cout);
  • D.

    std::ofstream outFile("log.txt");outFile << "Welcome to 2026!" << endl;outFile.close();

B

B 虽然打开了文件,但输出语句仍然写到了 cout,没有把 cout 重定向到文件,也没有写入 outFile,因此不能实现题目要求。

第 14 题

执行下面程序,输出结果是( )。

intdivi(int a, int b){if (b == 0throw0;return a / b;}intmain(){try {cout << divi(100);    } catch (constchar* msg) {cout << "A";    } catch (int) {cout << "B";    }}
  • A. A
  • B. B
  • C. 程序崩溃
  • D. 无输出

B

divi(10, 0) 执行时抛出的是整数 0,因此会被 catch(int) 捕获,输出 B

第 15 题

下列函数实现排行榜中单个元素的位置调整(类似插入排序的相邻搬移)。当某玩家分数增加,需将其向前移动时,while 循环的条件应为( )。

structPlayer {int score; };voidup(Player players[], int n, int idx){    Player cur = players[idx];int i = idx;while ( ____________________ ) {        players[i] = players[i - 1];        i--;    }    players[i] = cur;}
  • A. i > 0 && cur.score > players[i-1].score
  • B. i > 0 && cur.score < players[i-1].score
  • C. i < n-1 && cur.score > players[i+1].score
  • D. i < n-1 && cur.score < players[i+1].score

A

“向前移动”说明当前玩家要往更靠前的位置插入,只有当它前一位玩家分数比它低时,才需要继续前移。因此条件应为 i > 0 && cur.score > players[i-1].score

判断题

第 1 题

下面代码执行结束时,变量 a 的值变成 15。( )

voidadd10(int &x){ x += 10; }intmain(){int a = 5;    add10(a);}
  • A. 正确
  • B. 错误

A

add10 的参数是引用,调用 add10(a) 会直接修改变量 a 本身,因此 a 最终变为 15

第 2 题

引用一旦绑定某个变量,就不能再绑定其他变量。( )

  • A. 正确
  • B. 错误

A

引用本质上是某个对象的别名,初始化绑定后就不能改为引用别的变量。

第 3 题

执行下面代码,输出结果为 5。( )

intmain(){int a[2][3];cout << &a[1][2] - &a[0][1] << endl;return0;}
  • A. 正确
  • B. 错误

B

二维数组在内存中按行连续存放。a[0][1] 到 a[1][2] 中间跨过的是 4 个 int 元素,因此指针相减结果是 4,不是 5

第 4 题

下面程序可以正常编译并输出 10。( )

intcalc(int x, int y = 10);intcalc(int x)return x * 2; }intcalc(int x, int y)return x * y; }intmain(){cout << calc(5);}
  • A. 正确
  • B. 错误

B

调用 calc(5) 时,calc(int) 和带默认参数的 calc(int, int = 10) 都能匹配,造成重载调用二义性,程序不能正常通过编译。

第 5 题

下面程序执行后输出 2010。( )

int x = 10;voidf()int x = 20cout << x; }intmain(){    f();cout << x;}
  • A. 正确
  • B. 错误

A

函数 f() 中输出的是局部变量 x = 20,回到 main 后输出的是全局变量 x = 10,连起来正好是 2010

第 6 题

在 C++ 中,如果声明了一个指针变量但没有显式初始化,该指针会自动被初始化为 nullptr。( )

  • A. 正确
  • B. 错误

B

局部指针变量若未初始化,其值是不确定的,并不会自动变成 nullptr。只有静态存储期对象才会默认初始化为 0。

第 7 题

下面代码没有语法错误。( )

structGameCharacter {string name;int level;float position_x;float position_y;structEquipment {string weapon;int attack_bonus;int defense_bonus;    } equipment;structSkill {string name;int damage;    } skills[8];int skill_count;};
  • A. 正确
  • B. 错误

A

结构体内部再定义结构体类型,并同时声明成员对象或数组,这种写法在 C++ 中是合法的,因此该代码没有语法错误。

第 8 题

下面程序能够把 Hello 写入 data.txt 文件中。( )

ofstream fout("data.txt");cout << "Hello";fout.close();
  • A. 正确
  • B. 错误

B

程序把文本输出到了 cout,也就是标准输出,并没有写到文件流 fout 中,所以不能把 Hello 写入 data.txt

第 9 题

由于选择排序和插入排序的时间复杂度均为 ,在任何实际场景下两者的性能表现几乎相同,可以互相替代。( )

  • A. 正确
  • B. 错误

B

虽然它们的时间复杂度同为 ,但常数因子、数据分布适应性、是否稳定等性质不同,实际表现并不总是“几乎相同”,更不能简单认为可以在任何场景互相替代。

第 10 题

下面用递推方式计算斐波那契数列第 n 项的程序,时间复杂度是 。( )

intfib(int n){if (n <= 1return n;int f0 = 0, f1 = 1, cur = 0;for (int i = 2; i <= n; i++) {        cur = f0 + f1;        f0 = f1;        f1 = cur;    }return cur;}
  • A. 正确
  • B. 错误

B

该程序只用了一个从 2 到 n 的循环,每次循环执行常数次操作,所以时间复杂度是 ,不是 

编程题

第 1 题

山谷

题目描述

现有一片山地,可以视为一个  行  列的网格图,第  行第  列的海拔为 

如果一个单元格的海拔不高于其所有相邻单元格(相邻包括上、下、左、右、左上、右上、左下、右下,最多 8 个方向)的海拔,则称该单元格为山谷。

请你数一数这片山地中有多少山谷。

输入格式

第一行包含 2 个整数 N, M,表示山地的大小。

之后 N 行,每行包含 M 个整数 ,表示海拔。

输出格式

输出 1 行,包含 1 个整数 c,表示山谷的数量。

输入样例 1

3 57 6 6 7 96 5 6 7 66 5 7 8 9

输出样例 1

3

限制

  • 时间限制:1.0 s
  • 内存限制:512.0 MB

说明/提示

样例 1 如图所示,绿色单元格代表山谷。

GESP202603 C++四级真题“保姆级”详细题解 第4张

保证 

题解

这题没有隐藏做法,直接逐格判断就行。

一个格子是不是山谷,只和它周围 8 个方向的格子有关。所以把整个网格扫一遍,对每个位置 (i, j) 检查它附近的 3 × 3 区域:只要发现有哪个相邻格子的海拔比它更低,它就不可能是山谷;如果一圈看完都没有更低的,它就是山谷。

真正麻烦的地方只有边界。参考程序在网格外面补了一圈很大的数,当成哨兵。这样写以后,边上的格子也能直接按同一套循环去比较,不用专门分类讨论角落和边缘。

每个格子只会检查固定 9 个位置,所以总时间复杂度是 ,空间复杂度是 

代码

#include<iostream>usingnamespacestd;intmain(){int n, m;int h[105][105];cin >> n >> m;for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)cin >> h[i][j];for (int i = 0; i <= max(n, m) + 1; i++)        h[i][0] = h[0][i] = h[i][m + 1] = h[n + 1][i] = 1e9;int ans = 0;for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++) {bool ok = true;for (int i2 = i - 1; i2 <= i + 1; i2++)for (int j2 = j - 1; j2 <= j + 1; j2++)if (h[i][j] > h[i2][j2]) {                        ok = false;break;                    }            ans += ok;        }cout << ans;return0;}

第 2 题

礼盒排序

题目描述

商店推出了许多礼盒,每个礼盒中包含 k 件商品,每件商品都有一个价格。

现在需要对这些礼盒进行排序,排序规则如下:

  1. 先按礼盒总价格从小到大排序;
  2. 如果总价格相同,按礼盒中最贵商品的价格从小到大排序;
  3. 如果仍然相同,按礼盒中最便宜商品的价格从小到大排序;
  4. 如果仍然相同,按礼盒编号从小到大排序。

请输出排序后的礼盒编号。

输入格式

第一行包含两个整数 n 和 k,分别表示礼盒数量和每个礼盒中商品的数量。

接下来 n 行,每行包含 k 个整数,第 i 行表示第 i 个礼盒中各商品的价格。

输出格式

输出一行,包含排序后的礼盒编号(编号从 1 开始),用空格分隔。

输入样例 1

4 33 5 24 1 52 2 43 4 3

输出样例 1

3 4 2 1

限制

  • 时间限制:1.0 s
  • 内存限制:512.0 MB

说明/提示

4 个礼盒分别为:

编号
商品价格
总价
最大值
最小值
1
3 5 2
10
5
2
2
4 1 5
10
5
1
3
2 2 4
8
4
2
4
3 4 3
10
4
3

排序过程:

  1. 按总价排序,3 号礼盒总价最小;
  2. 其余总价均为 10,再按最大值排序,4 号最大值更小;
  3. 1 号和 2 号最大值相同,再按最小值排序,2 号更小。

最终顺序为:3 4 2 1

保证 ,商品价格 

题解

这题本质上是“先把信息算出来,再按规则排序”。

每个礼盒里虽然有 k 件商品,但真正参与比较的只有四个量:总价 sum、最高价 mx、最低价 mn、编号 id。所以读入每个礼盒时,顺手把这四个值统计出来,存进结构体里就够了。

后面就按题目给的顺序写比较函数:先比 sum,再比 mx,再比 mn,最后比 id。比较规则和题面完全一致,直接 sort 就能得到最终顺序。

读入和统计的代价是 ,排序是 ,总复杂度为 。额外空间主要就是保存所有礼盒信息,为 

代码

#include<iostream>#include<vector>#include<algorithm>usingnamespacestd;structCombo {int sum, mx, mn, id;};boolcmp(const Combo &a, const Combo &b){if (a.sum != b.sum) return a.sum < b.sum;if (a.mx != b.mx) return a.mx < b.mx;if (a.mn != b.mn) return a.mn < b.mn;return a.id < b.id;}intmain(){int n, k;cin >> n >> k;vector<Combo> v(n);for (int i = 0; i < n; i++) {        v[i].sum = 0;        v[i].mx = -1;        v[i].mn = 1e9;        v[i].id = i + 1;for (int j = 0; j < k; j++) {int x;cin >> x;            v[i].sum += x;            v[i].mx = max(v[i].mx, x);            v[i].mn = min(v[i].mn, x);        }    }    sort(v.begin(), v.end(), cmp);for (int i = 0; i < n; i++) {cout << v[i].id;if (i + 1 < n) cout << " ";    }cout << endl;return0;}

点击下载:202603GESP四级

暑期备战CSP-J/S,赛前集训全面提升!

由中美国信奥国家队教练团队授课,从零基础到高阶算法竞赛集训,NOI金牌选手等大咖云集交流分享...

2026 代码部落信奥夏令营,抢先预约名额,咨询老师:

GESP202603 C++四级真题“保姆级”详细题解 第5张

点击"阅读原文" 领取零基础体验课

抱歉,评论功能暂时关闭!