枚举区间内每个整数,再逐位统计其中数字 2 的出现次数并累加。
OJ: luogu
题目 ID: P1179
难度:入门
标签:模拟枚举
日期: 2026-06-18 23:20
题意
给定一个区间 [L, R],要求统计这个区间里所有整数的十进制表示中,数字 2 一共出现了多少次。
例如区间 [2, 22] 中:
2里有一个212里有一个220、21各有一个222里有两个2
把这些次数全部加起来就是答案。
思路
先看一个最容易理解的朴素解:
枚举区间里的每一个数,把它转成字符串,然后数一数里面有几个字符 '2'。
cpp
// brute.cpp:小数据暴力解,用来帮助理解题意并辅助对拍。
#include <bits/stdc++.h>
using namespace std;
int l, r;
int count_two(int x) {
string s = to_string(x);
int cnt = 0;
for (int i = 0; i < (int)s.size(); i++) {
if (s[i] == '2') {
cnt++;
}
}
return cnt;
}
void solve() {
int ans = 0;
for (int i = l; i <= r; i++) {
ans += count_two(i);
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> l >> r;
solve();
return 0;
}这份暴力已经可以通过本题,因为数据范围只有 1e5。
正式代码只是在“统计单个数里有几个 2”这一步换成了更贴近数位本质的写法:
- 用
x % 10取出当前最后一位 - 如果这一位等于
2,计数加一 - 再用
x /= 10删掉最后一位
这样不断拆位,直到这个数变成 0 为止。
最后把区间 [L, R] 中每个数贡献的 2 的个数累加起来即可。
代码
cpp
#include <bits/stdc++.h>
using namespace std;
int l, r;
// 统计单个整数中数字 2 出现了多少次。
int count_two(int x) {
int cnt = 0;
while (x > 0) {
if (x % 10 == 2) {
cnt++;
}
x /= 10;
}
return cnt;
}
void solve() {
int ans = 0;
for (int i = l; i <= r; i++) {
ans += count_two(i);
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> l >> r;
solve();
return 0;
}复杂度
设区间长度为 n = R - L + 1,每个数最多处理若干十进制位,所以时间复杂度是
总结
这题本质上就是“枚举 + 数位拆分统计”。
重点不是设计复杂算法,而是把“统计一个数里某个数字出现次数”这个子问题写清楚,然后顺着区间累加。