GESP 2026年6月真题编程题详解

四季读书网 6 0

GESP 2026年6月真题编程题详解

GESP 2026年6月真题编程题详解-第1张图片-四季读书网

> 前言:单看编程题,相较3月份难度要简单很多,像4,5,6级都是很常规的题目,7级暂时缺失题面,8级的编程题也只是模板稍微变形,没有很复杂的思维难度。

1级

T1 税收比例(缺题面)

常规语法题,如果涉及到小数注意保留小数位,目前缺题面不做赘述。

T2 旅行方案

题意从 A 到 B 有三种走法:直达、A 到 C 再飞机到 B、A 到 C 再高铁到 B。给出 4 个价格,求最便宜方案。

思路直接计算三种方案的费用并取最小值即可:

min(直达价, A->C高铁 + C->B飞机, A->C高铁 + C->B高铁)

复杂度O(1)。

参考代码

#include<bits/stdc++.h>usingnamespacestd;intmain(){longlong direct, trainAC, planeCB, trainCB;cin >> direct >> trainAC >> planeCB >> trainCB;cout << min({direct, trainAC + planeCB, trainAC + trainCB}) << '\n';return0;}

2级

T1 完全平方数

题意给定整数 l, r,统计区间 [l, r] 内有多少个完全平方数。

思路完全平方数就是 i*i。做法有两种:

  1. 直接枚举 i,看 i*i 是否落在区间内。
  2. 用公式:floor(sqrt(r)) - ceil(sqrt(l)) + 1,若结果为负则输出 0。

题目范围很小,直接枚举就够了。

复杂度O(sqrt(r))。

参考代码

#include<bits/stdc++.h>usingnamespacestd;intmain(){longlong l, r;cin >> l >> r;int ans = 0;for (longlong i = 0; i * i <= r; i++) {if (i * i >= l) ans++;    }cout << ans << '\n';return0;}

T2 打印菱形(缺题面)

常规语法题,注意空格的输出即可。

3级

T1 加密

题意给定数组 S 和长度为 9 的数组 A。对于 S 中每个值 k (0 <= k <= 8),把它替换成 A[k]。

思路这是一个直接映射问题,按位置替换即可。遍历 S,输出 A[S[i]]。

复杂度O(n)。

参考代码

#include<bits/stdc++.h>usingnamespacestd;intmain(){int n;cin >> n;vector<int> s(n), a(9);for (int i = 0; i < n; i++) cin >> s[i];for (int i = 0; i < 9; i++) cin >> a[i];for (int i = 0; i < n; i++) {if (i) cout << ' ';cout << a[s[i]];    }cout << '\n';return0;}

T2 字符串解密

题意对长度为 n 的字符串逐字符转换:

  • 小写字母变成对应大写字母;
  • 大写字母变成对应小写字母;
  • 数字字符变成 *;
  • 其他字符保持不变。

思路逐字符扫描一遍即可。判断字符类型后按规则转换,最后原样拼接输出。

复杂度O(n)。

参考代码

#include<bits/stdc++.h>usingnamespacestd;intmain(){int n;string s;cin >> n >> s;for (char &c : s) {if (c >= 'a' && c <= 'z') c = char(c - 'a' + 'A');elseif (c >= 'A' && c <= 'Z') c = char(c - 'A' + 'a');elseif (c >= '0' && c <= '9') c = '*';    }cout << s << '\n';return0;}

4级

T1 扫雷

题意给定一个 n x m 的地图和 p 个雷的位置。若当前位置是雷,输出 *;否则输出它 8 邻域内雷的数量。

思路先把雷的位置标记出来,然后对每个非雷格子统计周围 8 个方向的雷数。

可用两个数组表示方向:

dx = [-1,-1,-1,0,0,1,1,1]dy = [-1,0,1,-1,1,-1,0,1]

复杂度O(nm + p),或者直接按雷去更新邻格也可以。

参考代码

#include<bits/stdc++.h>usingnamespacestd;intmain(){int n, m, p;cin >> n >> m >> p;vector<vector<char>> grid(n, vector<char>(m, '0'));for (int i = 0; i < p; i++) {int r, c;cin >> r >> c;        grid[r - 1][c - 1] = '*';    }int dx[8] = {-1, -1, -1, 0, 0, 1, 1, 1};int dy[8] = {-1, 0, 1, -1, 1, -1, 0, 1};for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (grid[i][j] == '*') continue;int cnt = 0;for (int k = 0; k < 8; k++) {int x = i + dx[k], y = j + dy[k];if (0 <= x && x < n && 0 <= y && y < m && grid[x][y] == '*') {                    cnt++;                }            }            grid[i][j] = char('0' + cnt);        }    }for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) cout << grid[i][j];cout << '\n';    }return0;}

T2 身高指数

题意每个朋友有体重和身高,身高指数定义为 体重 / 身高^2。按身高指数从高到低排序并输出。

思路把每个人的 体重、身高 存起来,计算 BMI 后排序。身高是小数,建议用 long double 计算;如果担心精度,可用稳定排序保留原顺序。

复杂度O(n log n)。

参考代码

#include<bits/stdc++.h>usingnamespacestd;structPerson {int weight;string heightText;longdouble height;};intmain(){int n;cin >> n;vector<Person> people(n);for (int i = 0; i < n; i++) {cin >> people[i].weight >> people[i].heightText;        people[i].height = stold(people[i].heightText);    }    stable_sort(people.begin(), people.end(), [](const Person &a, const Person &b) {longdouble ia = a.weight / (a.height * a.height);longdouble ib = b.weight / (b.height * b.height);return ia > ib;    });for (auto &p : people) {cout << p.weight << ' ' << p.heightText << '\n';    }return0;}

5级

T1 最多糖果

题意有 n 个数,重新排列后,使“每个位置的值被它左边所有数反复累加”后的总和最大。

思路把大数放前面最优。交换论证很直接:如果较小的数在较前面,把它和较大的数交换,总贡献不会变差,通常会更大。所以按降序排序,然后依次累加前缀和,把每次前缀和累加到答案里。

复杂度O(n log n)。

参考代码

#include<bits/stdc++.h>usingnamespacestd;intmain(){int n;cin >> n;vector<longlong> a(n);for (int i = 0; i < n; i++) cin >> a[i];    sort(a.begin(), a.end(), greater<longlong>());longlong prefix = 0, ans = 0;for (longlong x : a) {        prefix += x;        ans += prefix;    }cout << ans << '\n';return0;}

T2 最大互质和

题意从给定的 n 个正整数中选出两个互质数,使它们的和最大。

思路n <= 1000,直接枚举所有数对,判断 gcd(a[i], a[j]) == 1,维护最大和即可。

复杂度O(n^2 log V)。

参考代码

#include<bits/stdc++.h>usingnamespacestd;intmain(){int n;cin >> n;vector<longlong> a(n);for (int i = 0; i < n; i++) cin >> a[i];longlong ans = 0;for (int i = 0; i < n; i++) {for (int j = i + 1; j < n; j++) {if (gcd(a[i], a[j]) == 1) {                ans = max(ans, a[i] + a[j]);            }        }    }cout << ans << '\n';return0;}

6级

T1 蛋糕切割

题意长度为 a 的蛋糕可以切成若干段,长度为 i 的蛋糕价值为 b[i]。求切割后的最大总价值。

思路这是完全背包 / 经典切木棍问题。dp[j] 表示长度为 j 的蛋糕能得到的最大价值。

转移:

dp[j] = max(dp[j], dp[j-i] + b[i])

其中 i 可以重复使用,所以枚举长度时,背包容量要正向更新。

复杂度O(a^2)。

参考代码

#include<bits/stdc++.h>usingnamespacestd;intmain(){int a;cin >> a;vector<longlong> value(a + 1), dp(a + 1, 0);for (int i = 1; i <= a; i++) cin >> value[i];for (int piece = 1; piece <= a; piece++) {for (int len = piece; len <= a; len++) {            dp[len] = max(dp[len], dp[len - piece] + value[piece]);        }    }cout << dp[a] << '\n';return0;}

T2 满子树计算

题意给定一棵二叉树,每个节点给出左右孩子编号(不存在则为 0)。统计其中有多少个节点为根的子树是满二叉树。

思路先找到整棵树的根节点,再自底向上判断每个子树:

  • 叶子节点:是满二叉树,高度为 1;
  • 若左右子树都存在,且左右子树都满二叉树,并且高度相同,则当前子树也是满二叉树;
  • 其他情况都不是。

遍历时顺便计数即可。

复杂度O(n)。

参考代码

#include<bits/stdc++.h>usingnamespacestd;intmain(){int n;cin >> n;vector<int> leftChild(n + 1), rightChild(n + 1), isChild(n + 1, 0);for (int i = 1; i <= n; i++) {cin >> leftChild[i] >> rightChild[i];if (leftChild[i]) isChild[leftChild[i]] = 1;if (rightChild[i]) isChild[rightChild[i]] = 1;    }int root = 1;for (int i = 1; i <= n; i++) {if (!isChild[i]) {            root = i;break;        }    }vector<int> order;    order.reserve(n);stack<int> st;    st.push(root);while (!st.empty()) {int u = st.top();        st.pop();        order.push_back(u);if (leftChild[u]) st.push(leftChild[u]);if (rightChild[u]) st.push(rightChild[u]);    }vector<int> height(n + 1, 0);vector<bool> full(n + 1, false);int ans = 0;    reverse(order.begin(), order.end());for (int u : order) {int l = leftChild[u], r = rightChild[u];if (l == 0 && r == 0) {            full[u] = true;            height[u] = 1;        } elseif (l != 0 && r != 0 && full[l] && full[r] && height[l] == height[r]) {            full[u] = true;            height[u] = height[l] + 1;        } else {            height[u] = max(height[l], height[r]) + 1;        }if (full[u]) ans++;    }cout << ans << '\n';return0;}

7级

暂时缺失

8级

T1 组合数计算

题意计算 C(n-1, m-1) mod (1e9+7)。约束保证 min(m-1, n-m) <= 2e6。

思路利用组合数对称性:

C(n-1, m-1) = C(n-1, k),  k = min(m-1, n-m)

然后计算:

num = (n-1) * (n-2) * ... * (n-k)den = k!ans = num * den^(mod-2) mod mod

其中 den^(mod-2) 用费马小定理求逆元。

复杂度O(k + log mod),k <= 2e6。

参考代码

#include<bits/stdc++.h>usingnamespacestd;constlonglong MOD = 1000000007LL;longlongmodPow(longlong a, longlong e){longlong ans = 1;    a %= MOD;while (e > 0) {if (e & 1) ans = ans * a % MOD;        a = a * a % MOD;        e >>= 1;    }return ans;}intmain(){longlong n, m;cin >> n >> m;longlong k = min(m - 1, n - m);longlong numerator = 1, denominator = 1;for (longlong i = 0; i < k; i++) {        numerator = numerator * ((n - 1 - i) % MOD + MOD) % MOD;        denominator = denominator * (i + 1) % MOD;    }longlong ans = numerator * modPow(denominator, MOD - 2) % MOD;cout << ans << '\n';return0;}

T2 网格上的有限距离最小生成树

题意平面上有 N 个点,边权是曼哈顿距离。只允许使用长度不超过 L 的边,求把所有点连通的最小总长度;若无法连通,输出 -1。

思路N <= 1000,可以直接建完全图:

  • 枚举所有点对,计算曼哈顿距离;
  • 若距离 <= L,就加入边集;
  • 对边集按权值排序,跑 Kruskal。

如果最后没选满 N-1 条边,说明无法连通,输出 -1。

复杂度O(N^2 log N)。

参考代码

#include<bits/stdc++.h>usingnamespacestd;structDSU {vector<int> parent, size;    DSU(int n) : parent(n), size(n, 1) {        iota(parent.begin(), parent.end(), 0);    }intfind(int x){while (x != parent[x]) {            parent[x] = parent[parent[x]];            x = parent[x];        }return x;    }boolunite(int a, int b){        a = find(a);        b = find(b);if (a == b) returnfalse;if (size[a] < size[b]) swap(a, b);        parent[b] = a;        size[a] += size[b];returntrue;    }};structEdge {int u, v;longlong w;};intmain(){int n;longlong limit;cin >> n >> limit;vector<pair<longlong, longlong>> point(n);for (int i = 0; i < n; i++) {cin >> point[i].first >> point[i].second;    }vector<Edge> edges;for (int i = 0; i < n; i++) {for (int j = i + 1; j < n; j++) {longlong dist = llabs(point[i].first - point[j].first)                           + llabs(point[i].second - point[j].second);if (dist <= limit) edges.push_back({i, j, dist});        }    }    sort(edges.begin(), edges.end(), [](const Edge &a, const Edge &b) {return a.w < b.w;    });DSU dsu(n);longlong ans = 0;int used = 0;for (const Edge &e : edges) {if (dsu.unite(e.u, e.v)) {            ans += e.w;            used++;        }    }cout << (used == n - 1 ? ans : -1) << '\n';return0;}

GESP历年各级真题题解⬅点我查看

END
GESP 2026年6月真题编程题详解-第2张图片-四季读书网
欢迎点赞、分享、推荐~感谢阅读!
信奥免费答疑咨询
分享信奥资讯
各种干货资源
最新通知公告

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