这道题,考的是"照着说明书做"
2025年9月GESP C++三级编程第一题「数组清零」,题目给了一套操作规则,让你模拟执行,数出总共操作了多少次。
这类题叫模拟法——题目说怎么做,代码就怎么做,一步不多一步不少。
难点不是想算法,而是把题目的文字规则,原原本本翻译成代码,并且处理好两个容易忽略的细节。
题目原文
数组清零(GESP C++ 三级,2025年9月)
小 A 有一个由 n 个非负整数构成的数组。他会对数组重复进行以下操作,直到数组中只包含 0:
- 找出值最大的元素,若有多个最大值,选其中下标最大的,记为位置 k
- 在所有非零元素里,找到值最小的元素
- 令 a[k] = a[k] - 最小值,操作次数加 1
请输出总操作次数。
样例输入 1:
3234
样例输出 1:
7
过程演示: [2,3,4] → [2,3,2] → [2,1,2] → [2,1,1] → [1,1,1] → [1,1,0] → [1,0,0] → [0,0,0]
样例输入 2:
513225
样例输出 2:
13
数据范围: 1 ≤ n ≤ 100,0 ≤ a[i] ≤ 100
家长速览
本篇核心: while(1) 主循环模拟每轮操作;找最大值用 >=(多个相等取下标最大);找最小值加 a[i]>0 过滤零;终止条件是最大值为 0。
第一步:读懂题,手算样例
拿样例 [2, 3, 4] 手算,逐步模拟:
操作 7 次,数组变为 [0,0,0],与样例吻合。
手算完再写代码,思路更清晰。

第二步:难点在哪里
难点一:找最大值,为什么用 >= 而不是 >?
题目说"多个最大值取下标最大的那个"。
- 用
>:遇到相等不更新,最后留下的是下标最小的最大值 - 用
>=:遇到相等也更新,最后留下的是下标最大的最大值
int mx =1;for(int i =1; i <= n; i++)if(a[i]>= a[mx]) mx = i;// >= ,相等也更新
第 3 轮手算里, [2,1,2] 的最大值是 2,位置 1 和位置 3 都是 2,用 >= 才能拿到位置 3。
难点二:找最小值,为什么要过滤零?
题目说"在所有非零元素里找最小值"。
如果不过滤,数组里已经变成 0 的元素会被当成最小值,然后每轮 a[mx]-=0,数组永远不会变化——程序死循环。
int mn = a[mx];// 初值用当前最大值for(int i =1; i <= n; i++)if(a[i]>0) mn = min(mn, a[i]);// 只看非零元素
这两个细节,是这道题考场上最常见的失分点。
第三步:破题思路
cnt =0while数组不全为0:找最大值位置 k(相等取下标最大,用>=)如果 a[k]==0,退出循环找非零元素里的最小值 mn(过滤零)a[k]-= mncnt++输出 cnt
这就是 SM-07 模拟法的六步框架:圈出状态变量( a[k] 和 cnt)→ 初始化 → 写主循环 → 写终止条件 → 检查边界 → 输出。
动手填一填:程序填空

#include<algorithm>#include<cstdio>usingnamespace std;constint N =105;int n, a[N], cnt;int main(){cnt =0;scanf("%d",&n);for(int i =1; i <= n; i++) scanf("%d",&a[i]);while(1){// 找最大值,多个相等取下标最大int mx =1;for(int i =1; i <= n; i++)if(____________________) mx = i;// ① 更新 mx 的条件if(a[mx]==0)break;// 最大值为 0,全部清零,退出// 找非零元素里的最小值int mn = a[mx];for(int i =1; i <= n; i++)if(____________________) mn = min(mn, a[i]);// ② 只看非零元素____________________;// ③ 执行操作cnt++;}printf("%d\n", cnt);return0;}
a[i]>=a[mx] | ||
a[i]>0 | ||
a[mx]-=mn; |
这道题考察的核心能力
>=>,遇到相等也更新 | |
mn=a[mx] | |
a[i]>0 |
同类题练一练
洛谷 P1009「阶乘之和」
循环迭代类模拟题,每轮计算当前阶乘并累加,直到满足条件退出。和数组清零一样,关键是初始化和终止条件写准。
小结
「数组清零」的核心是两个细节:
- 找最大值用
>=:遇到相等也更新,保证取到下标最大的那个 - 找最小值过滤零:加
a[i]>0,不然零会变成最小值,程序死循环
这两个地方写对,模拟过程照着题目规则翻译,就能拿满分。