这题到底在考什么
枚举 L 到 R 的每个整数,把每个数拆成一位一位看,统计数字 2 是否恰好出现 3 次。
对象
保留的信息只有当前数 y、当前个位 y % 10、已经数到的 2 的个数 cnt;原始 x 不参与判断后续位。
为什么能这样做
R 最大 10^6,最多检查一百万个数,每个数最多 7 位,直接枚举不会超时。
先避开的坑
学生最容易把“恰好 3 个 2”看成“至少 3 个 2”,或者只看个位不继续除以 10。
样例 2221 到 2223
演示进度
课堂要求:每一步都让学生说出当前保留了什么信息,以及下一步为什么不会漏答案。
把关键过程写成表
| x | 拆位过程 | cnt | 是否美丽 |
|---|---|---|---|
| 2221 | 1 -> 2 -> 2 -> 2 | 3 | 是 |
| 2222 | 2 -> 2 -> 2 -> 2 | 4 | 否 |
| 2223 | 3 -> 2 -> 2 -> 2 | 3 | 是 |
当堂检查
212322 有几个 2?
为什么要用临时变量 y=x?
代码读慢一点
#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;
}
读代码抓这几处
- 外层 for 枚举区间内每个数。
- 内层 while 用 %10 和 /10 逐位统计。
- 只有 cnt == 3 才给答案加一。
复杂度与常见错误
复杂度:时间 O((R-L+1) * log10 R),空间 O(1)。
- 把恰好写成至少。
- 忘记 y /= 10,导致死循环。
- 只看一次个位,漏掉高位。
源文件:GESP2/B4497.md · GESP2/B4497_solution.md