GESP2025年9月认证C++三级真题与解析(编程题1(数组清零))
一、先看原题:




二、题目解析
1、先不看代码,先讲故事 🧸
(1)🧸 故事背景
小 A 有一排 能量水晶,每一块水晶都有能量值:
[0, 2, 3, 4](2)他的目标只有一个:
👉 把所有水晶的能量变成 0
(3)但他不能随便减,必须按规定操作。
2、一次“合法操作”是怎样的?⚙️
每一轮操作,小 A 都要 严格做 3 件事:
✅ 第 1 步:找“最强水晶”
- 在数组里找 最大的数
- 如果有多个一样大 👉 选下标最大的那个
📌 例如:
[0,2, 3, 4] → 最大是 4(下标 3)✅ 第 2 步:找“最弱但还活着的水晶”
- 在 所有不为 0 的数 里
- 找 最小的那个
📌 例如:
[0, 2, 3, 4] → 最小非 0 是 2, 因为2是活着的。✅ 第 3 步:做减法!
- 用:
最大值 -= 最小非 0 值📌 所以:
4 - 2 = 2数组变成:
[0,2, 3, 2]👉 这算 1 次操作
✅ 第 4 步:一直重复,直到最后停止🛑
🔚 当数组里所有数都变成 0,就停!
[0,0, 0, 0]题目保证:
👉 一定能在有限次内变成全 0
3、本题可用模拟算法🧠
(1)模拟算法基本步骤。
模拟算法:
初始化状态变量; for (时间或次数) { 根据规则改变状态; if (满足条件) { 修改状态; } } 输出结果;(2) 本题三个核心步骤:
🌟 步骤 1:用 while 循环
👉 “只要还有非 0,就继续干!”
while (true) { // 找最大 // 如果最大是 0 → break }🌟 步骤 2:每一轮都“扫一遍数组”
因为你要:
- 找最大值
- 找最小非 0
👉 所以每一轮都要用 for 把数组看一遍
🌟 步骤 3:操作次数要数清楚
cnt++; // 每成功减一次,就 +14、参考程序
✅代码1
#include <iostream> using namespace std; int main() { int n; cin >> n; int a[105]; for (int i = 1; i <= n; i++) { cin >> a[i]; } int cnt = 0; // 记录操作次数 while (true) { // ① 找最大值的下标(如果相同,取下标大的) int maxPos = 1; for (int i = 1; i <= n; i++) { if (a[i] >= a[maxPos]) { maxPos = i; } } // 如果最大值已经是 0,说明全清零了 if (a[maxPos] == 0) break; // ② 找最小的非 0 值 int minVal = a[maxPos]; for (int i = 1; i <= n; i++) { if (a[i] > 0 && a[i] < minVal) { minVal = a[i]; } } // ③ 做减法 a[maxPos] -= minVal; cnt++; // 操作次数 +1 } cout << cnt << endl; return 0; } ✅代码2
#include <iostream> #include <algorithm> using namespace std; int main() { int n; cin >> n; int a[105]; for (int i = 0; i < n; i++) { cin >> a[i]; } int cnt = 0; // 操作次数 while (true) { // ① 排序 sort(a, a + n); // ② 如果最大值已经是 0,说明全清零 if (a[n - 1] == 0) break; // ③ 找最小的非 0 int minNonZero = 0; for (int i = 0; i < n; i++) { if (a[i] > 0) { minNonZero = a[i]; break; } } // ④ 用最大值减最小非 0 a[n - 1] -= minNonZero; // ⑤ 计数 cnt++; } cout << cnt << endl; return 0; } 5、本题用到的知识点:
| 考点 | 是否重要 |
|---|---|
| 数组遍历 | ⭐⭐⭐ |
| while 循环 | ⭐⭐⭐ |
| 最大 / 最小查找 | ⭐⭐⭐ |
| 规则理解能力 | ⭐⭐⭐⭐ |
| 模拟能力 | ⭐⭐⭐⭐ |
6、本题注意的 几 个关键问题 🧩
1️⃣ 每一步操作,是否和题目完全一致?
(1)常见错误 ❌
- 一次改了多个元素
- 偷偷合并了两次操作
(2) 正确做法 ✅
- 一次 while / for = 一次题目操作
📌 在这道题中:
a[maxPos] -= minVal; cnt++; (3) ✔ 一步一步来
2️⃣ 操作顺序不能乱 ⚠️
先找谁?
再做什么?
最后判断什么?
顺序一错,结果就错。
例子 🌰
题目说:
找最大值再找最小非 0再减
❌ 先减再找
❌ 一起找
3️⃣ 循环什么时候结束,一定要想清楚 🛑
(1) 常见错误
- 死循环
- 少算一次
- 多算一次
(2) 正确姿势
结束条件,一定来自“题目规则”
本题中:
if (a[maxPos] == 0) break;