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 }