2525 字
13 分钟
GESP 2025年C++二级编程题解析
2025/03/22
2025/09/30

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;
}

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;
}

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;
}
GESP 2025年C++二级编程题解析
https://yezi.press/posts/gesp/gesp-cpp2-2025/
作者
Yezi 叶子
发布于
2025/03/22
许可协议
CC BY-NC-SA 4.0