题目
题目大意
给出(a)、(b), 统计(a)和(b)(包含(a)和(b))之间的整数中, 数字(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)分别出现了多少次。(1 ≤ a, b ≤ 10^8)。注意, (a)有可能大于(b)。
题解
设(f_d(n))表示(0 cdots n)中数字(d)出现的个数, 则求的是(f_d(a) - f_d(b - 1))。
暴力显然是会(TLE)的, 我们可以分段来求。例如我们要求(0 cdots 234)中每个数字的个数, 可以分成一下几个区间:
- ([0, 9])
- ([10, 99])
- ([100, 199])
- ([200, 229])
- ([230, 234])
递归求解就可以了。
代码
#include <cstdio>
#include <cstring>
int a[10], b[10];
inline void DepthFirstSearch(const int &n, const int &m, register int *arr) {
register int x(n / 10), y(n % 10), temp(x);
for (register int i = 1; i <= y; i++) {
arr[i] += m;
}
for (int i = 0; i < 10; i++) {
arr[i] += m * x;
}
while (temp) {
arr[temp % 10] += m * (y + 1);
temp /= 10;
}
if (x) {
DepthFirstSearch(x - 1, m * 10, arr);
}
}
int main(int argc, char const *argv[]) {
register int x, y;
while (~scanf("%d %d", &x, &y) && (x || y)) {
if (x > y) x ^= y ^= x ^= y;
memset(a, 0, sizeof(a)),
memset(b, 0, sizeof(b));
DepthFirstSearch(x - 1, 1, a),
DepthFirstSearch(y, 1, b);
for (register int i(0); i < 10; ++i) {
printf(i == 9 ? "%d
" : "%d ", b[i] - a[i]);
}
}
return 0;
}