B4497 [GESP202603 二级] 数数

数位统计 / 区间枚举 / 恰好 3 个 2

一、先回答问题

这题到底在考什么

枚举 L 到 R 的每个整数,把每个数拆成一位一位看,统计数字 2 是否恰好出现 3 次。

对象

保留的信息只有当前数 y、当前个位 y % 10、已经数到的 2 的个数 cnt;原始 x 不参与判断后续位。

为什么能这样做

R 最大 10^6,最多检查一百万个数,每个数最多 7 位,直接枚举不会超时。

先避开的坑

学生最容易把“恰好 3 个 2”看成“至少 3 个 2”,或者只看个位不继续除以 10。

二、互动演示

样例 2221 到 2223

演示进度

课堂要求:每一步都让学生说出当前保留了什么信息,以及下一步为什么不会漏答案。

三、手推结果

把关键过程写成表

x拆位过程cnt是否美丽
22211 -> 2 -> 2 -> 23
22222 -> 2 -> 2 -> 24
22233 -> 2 -> 2 -> 23
四、自己选答案

当堂检查

212322 有几个 2?
为什么要用临时变量 y=x?
五、C++14 参考代码

代码读慢一点

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int L, R;
    cin >> L >> R;

    int ans = 0;
    for (int x = L; x <= R; x++) {
        int y = x;
        int cnt = 0;

        while (y > 0) {
            if (y % 10 == 2) {
                cnt++;
            }
            y /= 10;
        }

        if (cnt == 3) {
            ans++;
        }
    }

    cout << ans << '\n';
    return 0;
}

读代码抓这几处

六、收口

复杂度与常见错误

复杂度:时间 O((R-L+1) * log10 R),空间 O(1)。

源文件:GESP2/B4497.md · GESP2/B4497_solution.md