GESP C++ 三级必备编程程序(真题必背)

GESP C++ 三级必备编程程序(真题必背)

GESP 三级定位
模块在三级编程题中的地位必背程度
一维数组 + 模拟半壁江山,超过一半的编程题直接用到⭐⭐⭐⭐⭐
字符串遍历 / 计数第二高频,常与 ASCII、大小写、查找结合⭐⭐⭐⭐
枚举 + 判断核心算法,没有更复杂算法,关键是定范围与判定⭐⭐⭐⭐
位运算 + 进制三级独有特色,最容易丢分,套路固定⭐⭐⭐

三级编程题共 2 道、每道 25 分、共 50 分,题型就落在这四大块里。下面 7 个"程序骨架"覆盖了近三年绝大多数真题套路——背熟骨架结构 + 易错点,上机直接套即可。

真考提醒

不是死记代码,而是记"套路骨架"。考试会换数据、换表述、换变量名,但模式不变:数组题九成是"遍历 + 标记/计数/极值",字符串题是"遍历 + 判定/计数/反转",位运算是那几个固定套路。理解后比背更稳。


29.1 数组极值替换(数字替换 · 2024.12 真题)

考点:数组遍历 + 找最大/最小值 + 按规则替换(模拟)。

题面模板:给定 nn 个数和一个基准 kk。把所有 < k 的数替换成序列最小值,把 > k 的数替换成序列最大值,== k 不变;输出替换后的序列。

思路:先扫一遍求 mx/mn,再扫一遍按规则改写。注意极值初值要"极端"。

replace_extreme.cpp
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 1e5 + 5;
int a[N];

int main() {
int n, k;
cin >> n >> k;

int mx = -2e9, mn = 2e9; // 初值必须"极端",不能写 0
for (int i = 1; i <= n; i++) {
cin >> a[i];
mx = max(mx, a[i]);
mn = min(mn, a[i]);
}

for (int i = 1; i <= n; i++) {
if (a[i] < k) a[i] = mn; // 小于 k → 最小值
else if (a[i] > k) a[i] = mx; // 大于 k → 最大值
// 等于 k → 保持不变
}

for (int i = 1; i <= n; i++) {
cout << a[i] << " ";
}
cout << "\n";
return 0;
}
易错点
  1. mx/mn 初值别偷懒写 0——若序列全是负数,mn 会错。
  2. 三个分支要用 if / else if / 不变,别漏掉"等于 k 不变"的情况。
  3. 数据范围 n≤105n \le 10^5,数组要开 1e5+5,开小会 RE。

29.2 前缀和判平衡(平衡序列 · 2024.09 真题)

考点:数组 + 前缀和(累加器)。

题面模板:判断数组能否在某处切一刀,使前半部分和等于后半部分和。

思路:前后相等 ⟺ 存在某个前缀和 = 总和的一半。先求总和 sum,再从左到右累加 pre,一旦 pre * 2 == sum 即平衡(至少留一个元素给后半,所以只遍历到 n-1)。

前缀和判平衡序列

balanced_sequence.cpp
#include <iostream>
using namespace std;

int a[10005];

int main() {
int t;
cin >> t;
while (t--) { // 多组测试数据
int n;
cin >> n;
int sum = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
sum += a[i];
}

int pre = 0;
bool ok = false;
for (int i = 1; i < n; i++) { // 至少留 1 个给后半
pre += a[i];
if (pre * 2 == sum) { // 前半 = 总和一半 ⟺ 前后相等
ok = true;
break;
}
}
cout << (ok ? "Yes" : "No") << "\n";
}
return 0;
}
易错点
  1. 循环条件 i < n(不是 i <= n):后半至少要有一个元素,否则"切"在末尾没有意义。
  2. 用 pre * 2 == sum 代替 pre == sum / 2,避免整数除法把奇数总和吞掉。
  3. 多组输入时,每组都要重置 sum、pre、ok。

29.3 模拟法标准写法(数组清零 · 2025.09 真题)

考点:模拟算法——题目怎么说,代码就怎么写。

题面模板:重复操作直到数组全为 0:找出最大值(多个相等取下标最大的那个,记为 kk),在所有非零元素里找最小值,令 a[k] -= 最小值,操作次数 +1。输出总次数。

思路:while 主循环模拟每一轮;找最大值用 >=(相等时保留更大下标,从后往前扫最省事);找最小值要 a[i] > 0 过滤掉 0;终止条件是最大值已为 0。

array_clear.cpp
#include <iostream>
#include <algorithm>
using namespace std;

int a[105];

int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];

int cnt = 0;
while (true) {
// 找最大值,多个相等取最大下标:从后往前扫,用 >=
int mk = 1;
for (int i = n; i >= 1; i--)
if (a[i] >= a[mk]) mk = i;
if (a[mk] == 0) break; // 已经全 0,停止

// 找非零最小值
int mn = 2e9;
for (int i = 1; i <= n; i++)
if (a[i] > 0) mn = min(mn, a[i]);

a[mk] -= mn;
cnt++;
}
cout << cnt << "\n";
return 0;
}
易错点
  1. 找最大值的比较用 >= 而不是 >:题目规定"多个最大值取下标最大",从后往前扫恰好满足。
  2. 找最小值必须 a[i] > 0 跳过已清零的元素,否则会减到负数。
  3. 终止条件是"最大值 == 0",不是"数组长度变 0"。

29.4 字符串计数(词频统计 · 2025.03 真题)

考点:字符串遍历 + 大小写统一 + 计数(计数数组 / map)。

题面模板:给定 nn 个单词,忽略大小写,输出出现次数最多的单词(保证唯一,输出小写形式)。

思路:读入每个单词 → 统一转小写 → 用 map<string,int> 计数 → 边计数边维护最大值。

word_frequency.cpp
#include <iostream>
#include <string>
#include <map>
using namespace std;

int main() {
int n;
cin >> n;
map<string, int> cnt;
string best;
int bestc = 0;

for (int i = 0; i < n; i++) {
string w;
cin >> w;
for (char &c : w) // 大写转小写(引用 & 才能改原串)
if (c >= 'A' && c <= 'Z') c += 32;
cnt[w]++;
if (cnt[w] > bestc) { // 题目保证最高频唯一
bestc = cnt[w];
best = w;
}
}
cout << best << "\n";
return 0;
}
易错点
  1. 大小写统一是高频坑:'A'→'a' 差 32,且必须用引用 char &c 才能改到字符串本身。
  2. 若只统计 26 个小写字母的频次,可用 int cnt[26] = {0},下标用 c - 'a',比 map 更快也更不容易错。
  3. 维护最大值要在累加之后比较,顺序反了会漏掉首次出现的最高频词。

29.5 字符串遍历与 ASCII(字母求和 / 字符转换 · 2024.03、2026.06 真题)

考点:字符串遍历 + 字符判定(islower/isupper 或手判)+ ASCII 运算。

题面模板:遍历字符串,对每类字符按规则换算成数值并累加(小写字母常映射为字母序号 c-'a'+1,大写另行处理)。

思路:for (char c : s) 逐字符取;用 c >= 'a' && c <= 'z' 判定类别,再套换算公式。

letter_sum.cpp
#include <iostream>
#include <string>
using namespace std;

int main() {
int n;
cin >> n; // 先读个数(也可直接读字符串)
string s;
cin >> s;

long long sum = 0; // 累加器用 long long,防溢出
for (char c : s) {
if (c >= 'a' && c <= 'z')
sum += (c - 'a' + 1); // 小写 → 字母序号(a=1,b=2,...)
else if (c >= 'A' && c <= 'Z')
sum += (c - 'A' + 1); // 大写:按题意决定取正序号或取负
}
cout << sum << "\n";
return 0;
}
易错点
  1. 字符本质是 ASCII 整数,'a' 是 97;求字母序号要用 c - 'a' + 1,不是 c - 'a'。
  2. 题目若要求"大写取负值"或"只统计某类",看清规则再写分支。
  3. 累加结果可能很大,用 long long。

29.6 枚举 + sqrt 判完全平方数(完全平方数 · 2024.03 真题)

考点:枚举(两两组合)+ 完全平方数判定。

题面模板:给定 nn 个数,问有多少对 (i,j)(i,j)(i<ji<j)满足 a[i] + a[j] 是完全平方数。

思路:双重循环枚举所有数对;用 isSquare 判完全平方数——k = sqrt(x) 后回判 k*k == x,避免浮点误差。

perfect_square.cpp
#include <iostream>
#include <cmath>
using namespace std;

bool isSquare(long long x) {
if (x < 0) return false; // 负数不是完全平方数
long long k = sqrt(x);
return k * k == x; // 用整数回判,绕开浮点误差
}

int main() {
int n;
cin >> n;
long long a[100005];
for (int i = 0; i < n; i++) cin >> a[i];

long long ans = 0;
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
if (isSquare(a[i] + a[j])) ans++;
cout << ans << "\n";
return 0;
}
易错点
  1. 判完全平方数不要只写 sqrt(x) == (int)sqrt(x)——浮点误差会误判。务必 k*k == x 回判。
  2. 枚举数对用 j = i + 1 避免重复计数与自我配对。
  3. 数据较大时 a[i] + a[j] 可能超 int,用 long long。

29.7 位运算经典套路(奇偶校验 / 判断 2 的幂 · 三级特色)

考点:三级独有,套路固定,属于"背下来就得分"的送分题。

必背 6 个套路:

bitwise_patterns.cpp
#include <iostream>
using namespace std;

int main() {
int x;
cin >> x;

// 1) 判奇偶:看最低位
bool isOdd = (x & 1);

// 2) 判断 x 是不是 2 的幂(x>0 且二进制只有一个 1)
bool isPow2 = (x > 0) && ((x & (x - 1)) == 0);

// 3) 取最低位的 1(lowbit):x & -x
int low = x & (-x);

// 4) 把最低位的 1 清零:x & (x - 1)
int clearLow = x & (x - 1);

// 5) 取第 k 位(从 0 起)是否为 1:(x >> k) & 1
bool bitK = (x >> 2) & 1;

// 6) 统计 1 的个数(Brian Kernighan 法)
int c = 0, t = x;
while (t) { t &= (t - 1); c++; }

return 0;
}
套路速记
  • 奇偶 → x & 1
  • 2 的幂 → x > 0 && (x & (x-1)) == 0
  • 取某一位 → (x >> k) & 1
  • 数 1 的个数 → while(t){ t &= t-1; c++; }
  • 奇偶校验题(2025.06)就是反复用 x & 1 数最低位、再 x >>= 1 右移处理下一位。

29.8 三级编程题真题速查表(近三年)

刷题优先级

下表来自近 13 场三级真题统计。数组/字符串占编程题一半以上,位运算/进制是三级特色,枚举/模拟是核心算法。背完上面 7 个骨架,基本覆盖表中绝大多数"综合应用"以外的题目。

场次编程题1考点编程题2考点
2023.06春游数组标记+模拟综合应用枚举+判断
2023.09小杨的储蓄数组+模拟综合应用循环+数组
2023.12小猫分鱼枚举+倒推单位转换字符串+模拟
2024.03字母求和字符串遍历+ASCII完全平方数枚举+sqrt
2024.06移位位运算+枚举寻找倍数数组+模拟
2024.09平衡序列数组+前缀和回文拼接字符串+回文
2024.12数字替换数组+模拟打印数字数组+模拟打印
2025.032025数位处理+枚举词频统计字符串+计数
2025.06奇偶校验位运算+枚举分糖果数组+模拟
2025.09数组清零模拟日历制作模拟+日期
2025.12密码强度字符串判定小杨的智能设备模拟
2026.03二进制回文串进制+位运算+字符串凯撒密码字符串+枚举
2026.06字符转换字符串+枚举综合应用数组+模拟
上机自测清单

闭眼能写出来,才算"背完":

  • 数组读入后先求 mx/mn 再按规则改写
  • 前缀和判平衡:pre*2 == sum 且循环到 n-1
  • 模拟题 while 主循环 + 明确的终止条件
  • 字符串统一大小写用 char &c 引用
  • 判完全平方数用 k*k == x 回判
  • 位运算 6 个套路闭眼默写
SShowball OI知识手册