文章

【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$。


题目分析

这道题目是经典的“闭区间内符合特定条件的数字个数计数”问题。通过分析,它重点考察了两个能力:

  1. 范围遍历: 使用一个 for 循环,从起点 $L$ 遍历到终点 $R$。
  2. 数位判定: 对遍历到的每一个数字进行数位拆解,统计其中数字 2 出现的次数。

综合来看,这必然会形成一个嵌套循环(外层遍历范围,内层拆解数字),这也是 GESP 二级考试的核心考点之一。

具体拆解步骤:

  1. 读取输入的两个正整数 $L$ 和 $R$。
  2. 设定一个计数器变量(比如叫做 anscount),用于记录“美丽的正整数”的总个数,初始值为 0。
  3. 开启外层 for 循环,循环变量 $i$ 从 $L$ 开始,一直到 $R$ 结束(包含 $R$)。
  4. 在外层循环内部,取出当前的数字 $i$。由于我们要拆解这个数字来进行判断,且不能破坏外圈循环的索引 $i$,所以必须用一个临时变量 $temp = i$ 把这个数字接过来。
  5. 准备一个专门记录数字 $i$ 包含多少个 2 的计数器 count2,初始值为 0。
  6. 开启内层 while 循环对临时变量 $temp$ 进行数位分离。每次通过 temp % 10 剥下个位数字,如果这个个位数字是 2,就让 count2 加一。然后通过 temp / 10 丢掉这一位,继续判断下一位,直到 $temp$ 变成 0 循环终止。
  7. 内层循环结束后,检查 count2 的值是不是恰好等于 3(题目规定含有恰好 3 个 2 才是美丽数)。如果是,外层的总计数器 ans 就加一。
  8. 外圈循环彻底结束后,打印输出 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),考试认证学员交流,互帮互助

GESP/CSP 认证学习微信公众号
GESP/CSP 认证学习微信公众号
本文由作者按照 CC BY-NC-SA 4.0 进行授权