3425 字
17 分钟
GESP 2025年C++二级编程题解析
2025/03/22
2025/12/29

202503-1 等差矩阵#

题目描述

小 A 想构造一个 nnmm 列的矩阵,使得矩阵的每一行与每一列均是等差数列。小 A 发现,在矩阵的第 ii 行第 jj 列填入整数 i×ji \times j,得到的矩阵能满足要求。你能帮小 A 输出这个矩阵吗?

输入格式

一行,两个正整数 n,mn, m

输出格式

nn 行,每行 mm 个由空格分割的整数,表示小 A 需要构造的矩阵。

样例输入 1

3 4

样例输出 1

1 2 3 4
2 4 6 8
3 6 9 12

提示

对于所有测试点,保证 1n,m501\leq n,m \leq 50

代码解析

按照题目中给出的规律打印 n 行 m 列的矩阵即可,不需要用到数组相关知识。

#include<bits/stdc++.h>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++)
cout << i * j << ' ';
cout << endl;
}
return 0;
}

202503-2 时间跨越#

题目描述

假设现在是 yymmddhh 时而 kk 小时后是 yy'mm'dd'hh' 时,对于给定的 y,m,d,h,ky, m, d, h, k,小杨想请你帮他计算出对应的 y,m,d,hy', m', d', h' 是多少。

输入格式

输入包含五行,每行一个正整数,分别代表 y,m,d,h,ky, m, d, h, k

输出格式

输出四个正整数,代表 y,m,d,hy', m', d', h'

样例输入 1

2008
2
28
23
1

样例输出 1

2008 2 29 0

提示

对于全部数据,保证有 2000y30002000 \leq y \leq 30001m121 \leq m \leq 121d311 \leq d \leq 310h230 \leq h \leq 231k241 \leq k \leq 24。数据保证为合法时间。

闰年判断规则

  • 普通闰年:年份能被 44 整除,但不能被 100100 整除。
  • 世纪闰年:年份能被 400400 整除。

满足以上任意一条规则的年份就是闰年,否则是平年。

代码解析

代码看起来比较多,实际原理就是一小时一小时的去加,循环 k 次,简单的模拟这个过程即可,注意其中的小时、日、月的进位,以及大小月和闰年的判断。

#include<bits/stdc++.h>
using namespace std;
int main() {
int y, m, d, h, k, max_day;
cin >> y >> m >> d >> h >> k;
for (int i = 1; i <= k; i++) {
h++;
if (h > 23) {
h = 0;
d++;
switch (m) {
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
max_day = 31; break;
case 4: case 6: case 9: case 11:
max_day = 30; break;
case 2:
if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0)
max_day = 29;
else
max_day = 28;
break;
}
if (d > max_day) {
d = 1;
m++;
if (m > 12) {
m = 1;
y++;
}
}
}
}
cout << y << ' ' << m << ' ' << d << ' ' << h;
return 0;
}

若已经学了数组的话,可以把每月的天数存到数组里,只需要单独判断二月即可,上面解法中的 switch 结构就可以不用了。

#include<bits/stdc++.h>
using namespace std;
int main() {
int y, m, d, h, k, max_day;
int day[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
cin >> y >> m >> d >> h >> k;
for (int i = 1; i <= k; i++) {
h++;
if (h > 23) {
h = 0;
d++;
if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0)
day[2] = 29;
else
day[2] = 28;
if (d > day[m]) {
d = 1;
m++;
if (m > 12) {
m = 1;
y++;
}
}
}
}
cout << y << ' ' << m << ' ' << d << ' ' << h;
return 0;
}

202506-1 数三角形#

题目描述

直角三角形有两条直角边与一条斜边,设两条直角边的长度分别为 a,ba, b,则直角三角形的面积为 ab2\frac{ab}{2}

请你计算当直角边长 a,ba, b 均取不超过 nn 的正整数时, 有多少个不同的面积为整数的直角三角形。直角边长分别为 a,ba, ba,ba', b' 的两个直角三角形相同,当且仅当 a=aa = a', b=bb = b' 或者 a=ba = b', b=ab = a'

输入格式

一行,一个整数 nn,表示直角边长的最大值。

输出格式

输出一行,一个整数,表示不同的直角三角形数量。

样例输入 1

3

样例输出 1

3

样例输入 2

5

样例输出 2

9

提示

对于所有测试点,保证 1n10001 \leq n \leq 1000

代码解析

透过题目看本质,我们需要让两条直角边从 1 开始到 n 依次去枚举,枚举的过程中需要注意两个点:第一、两条边的乘积需要是 2 的倍数,第二、枚举的过程中不能有重复的数字,比如 2、5 和 5、2。

#include<bits/stdc++.h>
using namespace std;
int main() {
int n, cnt = 0;
cin >> n;
for (int i = 1; i <= n; i++)
// 从 i 开始枚举,保证 i 和 j 的组合不重复
for (int j = i; j <= n; j++)
if (i * j % 2 == 0)
cnt++;
cout << cnt;
return 0;
}

202506-2 幂和数#

题目描述

对于正整数 nn,如果 nn 可以表为两个 22 的次幂之和,即 n=2x+2yn = 2^x + 2^yx,yx, y 均为非负整数),那么称 nn 为幂和数。

给定正整数 l,rl, r,请你求出满足 lnrl \leq n \leq r 的整数 nn 中有多少个幂和数。

输入格式

一行,两个正整数 l,rl, r,含义如上。

输出格式

输出一行,一个整数,表示 l,rl, r 之间幂和数的数量。

样例输入 1

2 8

样例输出 1

6

样例输入 2

10 100

样例输出 2

20

提示

对于所有测试点,保证 1lr1041 \leq l \leq r \leq 10^4

代码解析 1

题目需要找到范围内满足 n=2x+2yn = 2^x + 2^y 的数字,这道题可以用二进制的思路来简化代码,我们知道 2m2^m 的二进制中只有一个 1 后面全是 0(如:8、16、32),那么满足这个条件的数字 n 分为两种(以八位二进制举例):

  1. (0000 1000) + (0001 0000) => (0001 1000) n 的二进制中有两个 1
  2. (0000 1000) + (0000 1000) => (0001 0000) n 的二进制中只有一个 1

所以我们只需要找出范围内二进制中 1 的个数为 1 或者 2 的数即可(1是特例,排除在外)

#include<bits/stdc++.h>
using namespace std;
int main() {
int l, r, cnt = 0;
cin >> l >> r;
for (int i = l; i <= r; i++) {
if (i == 1) continue;
int cnt1 = 0, n = i;
// 计算 n 的二进制中 1 的个数
while (n) {
if (n % 2 == 1) cnt1++;
n /= 2;
}
if (cnt1 == 2 || cnt1 == 1) cnt++;
}
cout << cnt;
return 0;
}

代码解析 2

如果还没有掌握二进制的知识,则需要枚举法,这里我们枚举 X 和 Y 作为题目中的 2x2^x2y2^y ,为了防止重复的 X 和 Y 组合,可以让 Y 从 X 开始枚举

#include<bits/stdc++.h>
using namespace std;
int main() {
int l, r, cnt = 0;
cin >> l >> r;
for (int i = l; i <= r; i++)
for (int X = 1; X<= i; X*=2)
for (int Y = X; Y <= i; Y*=2)
if (X + Y == i)
cnt++;
cout << cnt;
return 0;
}

202509-1 优美的数字#

题目描述

如果一个正整数在十进制下的所有数位都相同,小 A 就会觉得这个正整数很优美。例如,正整数 66 的数位都是 66,所以 66 是优美的。正整数 9999 的数位都是 99,所以 9999 是优美的。正整数 123123 的数位不都相同,所以 123123 并不优美。

小 A 想知道不超过 nn 的正整数中有多少优美的数字。你能帮他数一数吗?

输入格式

一行,一个正整数 nn

输出格式

一行,一个正整数,表示不超过 nn 的优美正整数的数量。

样例输入 1

6

样例输出 1

6

样例输入 2

2025

样例输出 2

28

提示

对于所有测试点,保证 1n20251 \leq n \leq 2025

代码解析

对于范围内的每一个数字进行数位剥离,重点是要判断他的每一位是否都相同,所以我们可以事先把他的各位保存到 t 中,然后在数位剥离的过程中判断当前末尾数是否等于 t,如果不相等则修改 flag 为 flase;

注意根据题意,10以内的数字都是优美数。

#include<bits/stdc++.h>
using namespace std;
int main() {
int n, cnt = 0;
cin >> n;
for (int i = 1; i <= n; i++) {
int x = i, t = x % 10;
bool flag = true;
while (x) {
if (t != x % 10) {
flag = false;
break;
}
x /= 10;
}
if (flag || i < 10) cnt++;
}
cout << cnt;
return 0;
}

202509-2 菱形#

题目描述

小 A 想绘制一个菱形。具体来说,需要绘制的菱形是一个 nnnn 列的字符画,nn 是一个大于 11 的奇数。菱形的四个顶点依次位于第 11 行、第 11 列、第 nn 行、第 nn 列的正中间,使用 # 绘制。相邻顶点之间也用 # 连接。其余位置都是 .

例如,一个 5555 列的菱形字符画是这样的:

..#..
.#.#.
#...#
.#.#.
..#..

给定 nn,请你帮小 A 绘制对应的菱形。

输入格式

一行,一个正整数 nn

输出格式

输出共 nn 行,表示对应的菱形。

样例输入 1

3

样例输出 1

.#.
#.#
.#.

样例输入 2

9

样例输出 2

....#....
...#.#...
..#...#..
.#.....#.
#.......#
.#.....#.
..#...#..
...#.#...
....#....

提示

对于所有测试点,保证 3n293 \leq n \leq 29 并且 nn 为奇数。

代码解析

看似复杂,实际只需要找出来 # 的规律即可,这里可以分为上半部分和下半部分分别绘制,以九行为例:

第 1 行 # 的位置:5(5+0 和 5-0)

第 2 行 # 的位置:4、6(5+1 和 5-1)

第 3 行 # 的位置:3、7(5+2 和 5-2)

第 i 行 # 的位置: 5+(i - 1) 和 5 - (i - 1),这里的 5 就是 9/2+1

#include<bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
for (int i = 1; i <= n/2+1; i++) {
for (int j = 1; j <= n; j++)
if (j == n/2+1 + (i-1) || j == n/2+1 - (i-1))
cout << '#';
else
cout << '.';
cout << endl;
}
// 下半部分 i 逆序即可,内层不变
for (int i = n/2; i >= 1; i--) {
for (int j = 1; j <= n; j++)
if (j == n/2+1 + (i-1) || j == n/2+1 - (i-1))
cout << '#';
else
cout << '.';
cout << endl;
}
return 0;
}

202512-1 环保能量球#

题目描述

小杨最近在玩一个环保主题的游戏。在游戏中,小杨每行走 1 公里就可以获得 1 点“环保能量”。

为了激励玩家,游戏设置了“里程奖励”:小杨每行走 xx 公里,游戏就会额外奖励 1 点能量。

现在已知小杨总共行走了 nn 公里,请你帮他计算,他一共能获得多少点环保能量?

输入格式

第一行包含一个正整数 tt,代表测试数据组数。

对于每组测试数据:

  • 第一行包含一个正整数 nn,代表行走的公里数。
  • 第二行包含一个正整数 xx,代表奖励触发的间隔。

输出格式

对于每组测试数据,输出一个整数,代表小杨获得的环保能量总数。

样例输入 1

3
5
2
10
3
2
5

样例输出 1

7
13
2

提示

样例解释

  • 对于第 1 组数据,n=5,x=2n = 5, x = 2:小杨行走获得 55 点能量。此外,他在第 22 公里和第 44 公里时各获得 11 点额外奖励,总共 5+2=75 + 2 = 7 点。
  • 对于第 2 组数据,n=10,x=3n = 10, x = 3:行走获得 1010 点。他在第 336699 公里时各获得 11 点额外奖励,总共 10+3=1310 + 3 = 13 点。
  • 对于第 3 组数据,n=2,x=5n = 2, x = 5:行走获得 22 点。由于行走路程不足 55 公里,没有额外奖励,总共 22 点。

数据范围

对于全部数据,保证:1t1001 \leq t \leq 1001n,x10001 \leq n, x \leq 1000

代码解析

根据题意,每公里获得 11 点能量,基础能量为 nn 点,每 xx 公里额外获得 11 点能量,也就是 n/xn / x 整除的结果。

#include <bits/stdc++.h>
using namespace std;
int main() {
int t, n, x;
cin >> t;
while (t--) {
cin >> n >> x;
cout << n + n / x << endl;
}
return 0;
}

202512-2 黄金格#

题目描述

小杨在探险时发现了一张神奇的矩形地图,地图有 HH 行和 WW 列。每个格子的坐标是 (r,c)(r, c),其中 rr 表示行号从 11HHcc 表示列号 11WW

小杨听说地图中隐藏着一些“黄金格”,这些格子满足一个神秘的数学挑战:当格子坐标 (r,c)(r, c) 代入特定的不等式关系成立时,该格子就是黄金格。具体来说,黄金格的条件是:r2+c2x+rc\sqrt{r^2 + c^2} \leq x + r - c

例如,如果参数 x=5x = 5,那么格子 (4,3)(4, 3) 就是黄金格。因为左边坐标平方和的平方根 42+32\sqrt{4^2 + 3^2} 算出来是 55,而右边 5+435 + 4 - 3 算出来是 6655 小于等于 66,符合条件。

输入格式

三行,每行一个正整数,分别表示 H,W,xH,W,x。含义如题面所示。

输出格式

一行一个整数,代表黄金格数量。

样例输入 1

4
4
2

样例输出 1

4

提示

样例解释

图中标注为黄色的四个格子是黄金格,坐标分别为 (1,1)(1, 1)(2,1)(2, 1)(3,1)(3, 1)(4,1)(4, 1)

数据范围

对于所有测试点,保证给出的正整数不超过 10001000

代码解析

根据题意,我们需要遍历地图中的每一个格子 (r,c)(r, c),判断是否满足 r2+c2x+rc\sqrt{r^2 + c^2} \leq x + r - c。如果满足,就将计数器 cnt 加一。

#include <bits/stdc++.h>
using namespace std;
int main() {
int h, w, x, cnt = 0;
cin >> h >> w >> x;
for(int r = 1; r <= h; r++)
for(int c = 1; c <= w; c++)
if (sqrt(r*r+c*c) <= x+r-c)
cnt++;
cout << cnt;
return 0;
}
GESP 2025年C++二级编程题解析
https://yezi.press/posts/gesp/gesp-cpp2-2025/
作者
Yezi 叶子
发布于
2025/03/22
许可协议
CC BY-NC-SA 4.0