BZOJ1833: [ZJOI2010]count 數字計數(數位Dp)
阿新 • • 發佈:2019-01-01
Description
給定兩個正整數a和b,求在[a,b]中的所有整數中,每個數碼(digit)各出現了多少次。Input
輸入檔案中僅包含一行兩個整數a、b,含義如上所述。Output
輸出檔案中包含一行10個整數,分別表示0-9在[a,b]中出現了多少次。Sample Input
1 99Sample Output
9 20 20 20 20 20 20 20 20 20HINT
30%的資料中,a<=b<=10^6;
100%的資料中,a<=b<=10^12。
解題思路:
考慮一個位置上出現某個數的次數,那麼就要考慮其前面的情況*後面的情況就好了。
程式碼:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 typedef long long lnt; 5 lnt p[100]; 6 lnt ans[10]; 7 void solve(lnt lim,lnt f) 8 { 9 if(lim==-1) 10 return ; 11 for(int h=1;p[h-1]<=lim;h++) 12 { 13 lnt di=(lim/p[h-1])%10; 14 lnt dl=lim/p[h]; 15 lnt dr=lim%p[h-1]; 16 if(di) 17 ans[0]+=f*(dl*p[h-1]); 18 else 19 ans[0]+=f*((dl-1)*p[h-1]+dr+1); 20 for(int a=1;a<10;a++) 21 { 22 di=(lim/p[h-1])%10; 23 dl=lim/p[h]; 24dr=lim%p[h-1]; 25 if(a<di) 26 ans[a]+=f*(p[h-1]*(dl+1)); 27 else if(a==di) 28 ans[a]+=f*(p[h-1]*dl+dr+1); 29 else 30 ans[a]+=f*(p[h-1]*dl); 31 } 32 } 33 return ; 34 } 35 int main() 36 { 37 p[0]=1; 38 for(int i=1;i<=50;i++) 39 p[i]=p[i-1]*10ll; 40 lnt l,r; 41 scanf("%lld%lld",&l,&r); 42 if(l==0) 43 ans[0]++; 44 solve(r,1); 45 solve(l-1,-1); 46 for(int i=0;i<10;i++) 47 printf("%lld ",ans[i]); 48 return 0; 49 }