【数位dp】bzoj1833: [ZJOI2010]count 数字计数

数位dp姿势一直很差啊;顺便庆祝一下1A

Description

给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次。

Input

输入文件中仅包含一行两个整数a、b,含义如上所述。

Output

输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次。

Sample Input

1 99

Sample Output

9 20 20 20 20 20 20 20 20 20

HINT

30%的数据中,a<=b<=10^6;
100%的数据中,a<=b<=10^12。


 

题目分析

数位dp经典入门题

说到底,数位dp快就快在按位计算答案,而不是按数计算答案。

这个有些抽象,所以还是看代码吧。

 1 #include<bits/stdc++.h>
 2 typedef long long ll;
 3 
 4 ll a,b,ans[23];
 5 ll digit[23];
 6 ll base[15];
 7 
 8 ll read()
 9 {
10     char ch = getchar();
11     ll num = 0;
12     bool fl = 0;
13     for (; !isdigit(ch); ch = getchar())
14         if (ch=='-') fl = 1;
15     for (; isdigit(ch); ch = getchar())
16         num = (num<<1)+(num<<3)+ch-48;
17     if (fl) num = -num;
18     return num;
19 }
20 void work(ll num, ll c)
21 {
22     for (digit[0]=0; num; num/=10)
23         digit[++digit[0]] = num%10;
24     for (int i=digit[0]; i; i--)
25     {
26         for (int j=digit[0]; j>i; j--)
27             ans[digit[j]] += c*(digit[i]*base[i]);
28         for (int j=0; j<digit[i]; j++)
29         {
30             for (int k=0; k<=9; k++)
31                 ans[k] += c*base[i-1]*(i-1);
32             ans[j] += c*(base[i]);
33         }
34         if (i==digit[0]){
35             ans[0] -= c*digit[0];
36             for (int j=1; j<digit[0]; j++)
37                 ans[0] -= c*j*base[digit[0]-j]*9;
38         }
39     }
40 }
41 int main()
42 {
43     base[1] = 1;
44     for (int i=2; i<=13; i++) base[i] = base[i-1]*10ll;
45     a = read(), b = read()+1;
46     work(a, -1);
47     work(b, 1);
48     for (int i=0; i<=9; i++)
49         printf("%lld ",ans[i]);
50     return 0;
51 }

 

 

END

posted @ 2018-07-22 18:04  AntiQuality  阅读(224)  评论(0编辑  收藏  举报