【GESP】C++二级真题 luogu-B4497, [GESP202603 二级] 数数
2026年3月,GESP二级真题,考察嵌套循环与数位分离,难度★★☆☆☆。洛谷难度入门。
B4497 [GESP202603 二级] 数数
题目要求
题目描述
对于正整数 $n$,如果 $n$ 的所有数位中包含恰好 $3$ 个 $2$,Alice 会认为这个正整数是美丽的。例如,正整数 $24122$ 中包含 $3$ 个 $2$,所以 $24122$ 是美丽的;正整数 $132$ 中包含 $1$ 个 $2$,所以 $132$ 不是美丽的;正整数 $212322$ 中包含 $4$ 个 $2$,所以 $212322$ 不是美丽的。
Alice 想知道正整数 $L$ 到正整数 $R$(包括 $L$ 和 $R$)中有多少美丽的正整数,你能帮她数一数吗?
输入格式
输入共 $2$ 行,第一行为正整数 $L$,第二行为正整数 $R$。
输出格式
输出一行,包含一个整数 $C$,表示 $L$ 到 $R$ 中 $C$ 美丽数的数量。
输入输出样例 #1
输入 #1
1
2
2221
2223
输出 #1
1
2
说明/提示
样例解释
$2221$ 到 $2223$ 中,$2221$ 与 $2223$ 是美丽的,$2222$ 不是美丽的。
数据范围
保证 $1 \le L \le R \le 10^6$。
题目分析
这道题目是经典的“闭区间内符合特定条件的数字个数计数”问题。通过分析,它重点考察了两个能力:
- 范围遍历: 使用一个
for循环,从起点 $L$ 遍历到终点 $R$。 - 数位判定: 对遍历到的每一个数字进行数位拆解,统计其中数字
2出现的次数。
综合来看,这必然会形成一个嵌套循环(外层遍历范围,内层拆解数字),这也是 GESP 二级考试的核心考点之一。
具体拆解步骤:
- 读取输入的两个正整数 $L$ 和 $R$。
- 设定一个计数器变量(比如叫做
ans或count),用于记录“美丽的正整数”的总个数,初始值为 0。 - 开启外层
for循环,循环变量 $i$ 从 $L$ 开始,一直到 $R$ 结束(包含 $R$)。 - 在外层循环内部,取出当前的数字 $i$。由于我们要拆解这个数字来进行判断,且不能破坏外圈循环的索引 $i$,所以必须用一个临时变量 $temp = i$ 把这个数字接过来。
- 准备一个专门记录数字 $i$ 包含多少个
2的计数器count2,初始值为 0。 - 开启内层
while循环对临时变量 $temp$ 进行数位分离。每次通过temp % 10剥下个位数字,如果这个个位数字是2,就让count2加一。然后通过temp / 10丢掉这一位,继续判断下一位,直到 $temp$ 变成 0 循环终止。 - 内层循环结束后,检查
count2的值是不是恰好等于 3(题目规定含有恰好 3 个 2 才是美丽数)。如果是,外层的总计数器ans就加一。 - 外圈循环彻底结束后,打印输出
ans的结果即可。
示例代码
二级传统解法(推荐)
按照二级考纲要求,熟练使用嵌套循环和取模整除进行数位分离即可解答。代码中避免使用了 using namespace std; 保持良好的书写规范。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
int main() {
// 1. 读入范围起点 L 和终点 R
int L, R;
std::cin >> L >> R;
// 2. 准备用于记录符合条件的"美丽数"的总数的变量
int ans = 0;
// 3. 外层循环:遍历从 L 到 R 之间的每一个正整数 i
for (int i = L; i <= R; i++) {
// 4. 用临时变量接住 i,准备进行拆解
int temp = i;
// 5. 准备用于记录当前这个数字包含几个 '2' 的变量
int count2 = 0;
// 6. 内层循环:经典的数位分离
while (temp > 0) {
// 获取当前最末位的数字
int digit = temp % 10;
// 如果这个末位数字是 2,把计数器加一
if (digit == 2) {
count2++;
}
// 剥掉已经检查过的最末位
temp = temp / 10;
}
// 7. 内层剥离结束后,判断数字 '2' 出现的次数是否恰好等于 3
if (count2 == 3) {
ans++; // 恰好是3次,说明找到一个美丽数,总数加一
}
}
// 8. 循环外输出最终找到的总个数
std::cout << ans << std::endl;
return 0;
}
拓展解法(转字符串统计)
如果已经学习了三级的字符串(std::string)知识以及函数封装的概念,我们可以换一个思路:数字在计算机眼中也可以仅仅是一段文字。我们如果把数字转换成一串文字,去统计这段文字里面字符 '2' 出现的频率,也能达到同样的效果。
C++11 提供了 std::to_string() 方法可以直接将整数转换为字符串,代码如下供参考拓展。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <string>
// 写一个函数专门用来判断一个数字是不是”美丽“的
bool isBeautiful(int num) {
// 将数字转换成文字(字符串)
std::string str = std::to_string(num);
int count2 = 0;
// 遍历这串文字的每一个字符
for (int i = 0; i < str.length(); i++) {
// 如果遇到了字符 '2'
if (str[i] == '2') {
count2++;
}
}
// 如果字符 '2' 恰巧出现了 3 次,返回 true,否则返回 false
return count2 == 3;
}
int main() {
int L, R;
std::cin >> L >> R;
int ans = 0;
for (int i = L; i <= R; i++) {
// 调用我们自定义的函数进行判定
if (isBeautiful(i)) {
ans++;
}
}
std::cout << ans << std::endl;
return 0;
}
所有代码已上传至Github:https://github.com/lihongzheshuai/yummy-code
GESP 学习专题站:GESP WIKI
“luogu-”系列题目可在洛谷题库进行在线评测。
“bcqm-”系列题目可在编程启蒙题库进行在线评测。
欢迎加入:Java、C++、Python技术交流QQ群(982860385),大佬免费带队,有问必答
欢迎加入:C++ GESP/CSP认证学习QQ频道,考试资源总结汇总
欢迎加入:C++ GESP/CSP学习交流QQ群(688906745),考试认证学员交流,互帮互助
