(数位DP)51NOD 1042 数字0-9的数量

给出一段区间a-b,统计这个区间内0-9出现的次数。
比如 10-19,1出现11次(10,11,12,13,14,15,16,17,18,19,其中11包括2个1),其余数字各出现1次。
 

输入

两个数a,b(1 <= a <= b <= 10^18)

输出

输出共10行,分别是0-9出现的次数

输入样例

10 19

输出样例

1
11
1
1
1
1
1
1
1
1

解:被这道题卡了好久。。。最后自己找了个数模拟了一边流程。
举个例子简单说说:对于数5314,我们可以将它拆分为【5310-5314】【5300-5309】【5000-5299】【0-4999】(注意删去前置0)这几个区间计算,以此得出答案。
 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <math.h>
 4 
 5 long long num[2][10],res,a,b;
 6 
 7 void func(long long *tmp,long long *p,long long power)
 8 {
 9     if (power == 1) res = 0;
10     int t = *tmp % 10;
11     if (*tmp == 0)
12     {
13         int n = log10((double)power);
14         power /= 10;
15         for (int i = 1; i < n; ++i) p[0] -= 9 * (power /= 10) * i;
16         p[0] -= n - 1;
17         return;
18     }
19     *tmp /= 10;
20     if (res == 0) t++;
21     long long v= (long long)log10((double)power) * power / 10 * t;
22     for (int i = 9; i >= t; --i) p[i] += v;
23     for (int i = 0; i < t; ++i) p[i] += power + v;
24     p[t] += res;    
25     res += t * power;
26     func(tmp, p, power * 10);
27     return;
28 }
29 int main()
30 {
31     while (scanf_s("%lld%lld", &a, &b) != EOF)
32     {
33         memset(num, 0, sizeof num);
34         a--;
35         func(&a, num[0], 1);
36         func(&b, num[1], 1);
37         for (int i = 0; i < 10; ++i) printf("%lld\n", num[1][i] - num[0][i]);
38     }
39     return 0;
40 }
当然也可以分别计算0-9的个数,但我不想继续琢磨了。。。

猜你喜欢

转载自www.cnblogs.com/Ekalos-blog/p/10745817.html