Bzoj1833 [ZJOI2010]count 数字计数

1833: [ZJOI2010]count 数字计数

Time Limit: 3 Sec  Memory Limit: 64 MB

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。

 

Solution:

  一道不算特别裸的数位dp,需要预处理一下每一个长度所包含的数字个数,并且前导零很恶心。

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 long long  l,r,bit[15],f[15],c[15],p[15];
 7 long long dfs(int pos,int pre,int Dig,bool Limit) {
 8     if(pos<=0) return 0;
 9     if(pre>=0&&!Limit&&f[pos]!=-1) return f[pos];
10     int End=Limit?bit[pos]:9;
11     long long ans=0;
12     for(int i=0; i<=End; ++i) {
13         if(pre<0&&!i) ans+=dfs(pos-1,pre,Dig,Limit&&i==End);
14         else if(i==Dig) {
15             if(i==End&&Limit) ans+=c[pos-1]+1+dfs(pos-1,i,Dig,Limit&&i==End);
16             else ans+=p[pos-1]+dfs(pos-1,i,Dig,Limit&&i==End);
17         } else ans+=dfs(pos-1,i,Dig,Limit&&i==End);
18     } if(pre>=0&&!Limit) f[pos]=ans;
19     return ans;
20 }
21 long long Get(long long x,int dig) {
22     memset(f,0xff,sizeof(f));
23     memset(bit,0,sizeof(bit));
24     while(x) bit[++bit[0]]=x%10,x/=10,c[bit[0]]=c[bit[0]-1]+bit[bit[0]]*p[bit[0]-1];
25     return dfs(bit[0],-10,dig,true);
26 }
27 int main() {
28     scanf("%lld%lld",&l,&r); --l;
29     p[0]=1; for(int i=1; i<15; ++i) p[i]=p[i-1]*10;
30     for(int i=0; i<=9; ++i) {
31         printf("%lld",Get(r,i)-Get(l,i));
32         if(i<9) putchar(' ');
33     } return 0;
34 }

 

 

 

 

posted @ 2017-11-01 16:51  Forever_goodboy  阅读(318)  评论(0编辑  收藏  举报