枚举 M 到 N 的每个整数,用取模拆位统计 0..9 出现次数,避免 str 带来的常数开销。
OJ: luogu
题目 ID: P1554
难度:入门
标签:模拟计数python
日期: 2026-07-15 18:48
题意
给出整数区间 [M, N],统计从 M 数到 N 的过程中,数字 0..9 各出现了多少次。
思路
题目保证 N - M <= 5 * 10^5,可以直接枚举区间中的每个整数。
对每个整数 value,反复:
count[value % 10] += 1统计最低位;value //= 10去掉最低位;
直到变成 0。
例如 129 会依次贡献 9、2、1 三个数码。
注意:不要用 str(value) 拆位。区间最长约 5 * 10^5,每个数最多 10 位,总操作约 5 * 10^6。算法量级足够,但 Python 里反复创建字符串的常数偏大,最坏点可能 TLE。取模拆位更稳。
这题是直接计数练习,正解就是按定义枚举,不创建 brute.py。
Python 知识
/home/rainboy/mycode/hugo-blog/content/program_language/python/input_output_and_strings.md:用map(int, input().split())读取区间左右端点。/home/rainboy/mycode/hugo-blog/content/program_language/python/collections_toolkit.md:计数可以用列表或Counter;本题数码固定为0..9,列表更直接。x % 10/x //= 10是整数拆位的常用写法,比str更省常数。while True再在末尾if x == 0: break,保证至少统计一位(本题M >= 1)。
代码
python
left, right = map(int, input().split())
count = [0] * 10
for value in range(left, right + 1):
x = value
while True:
count[x % 10] += 1
x //= 10
if x == 0:
break
print(*count)cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-07-27 00:00
* update_at: 2026-07-27 00:00
*/
#include <bits/stdc++.h>
using namespace std;
int cnt[10]; // cnt[d] 记录数字 d 出现的次数
int m, n;
int main() {
cin >> m >> n;
for (int x = m; x <= n; x++) {
int t = x;
// 不断取最低位,统计数码
while (t) {
cnt[t % 10]++;
t /= 10;
}
}
for (int i = 0; i <= 9; i++) cout << cnt[i] << " ";
return 0;
}复杂度
设区间长度为 L = N-M+1,每个数字位数最多 10 位,时间复杂度可看作
总结
范围差已经限制在可直接枚举的规模内。拆位时优先用取模,而不是字符串,才能在 Python 下稳定通过最坏数据。