BZOJ1833

来源:互联网 发布:主题软件下载 编辑:程序博客网 时间:2024/06/07 18:04

1833: [ZJOI2010]count 数字计数

Time Limit: 3 Sec  Memory Limit: 64 MB
Submit: 1208  Solved: 552
[Submit][Status]

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,建一个数组 f [ i ][ j ][ k ], i表示第 i 位,j 表示最高位是 j ,k 表示0~9出现个数。然后通过一系列的处理得到答案。计算的过程数值很大,记得开long long.


#include<cstdio>#include<cstring>#define LL long longint ax[15],bx[15];LL f[15][10][10],va[15],vb[15];inline void swap(LL &x,LL &y){LL t=x;x=y;y=t;}inline LL ff(int x){LL tot=1;for(int i=1;i<=x;i++)tot*=10;return tot; }int main(){LL a,b;int la=0,lb=0;scanf("%lld%lld",&a,&b);if(a>b)swap(a,b);b++;while(b){bx[++lb]=b%10;b/=10;}while(a){ax[++la]=a%10;a/=10;}if(!la)ax[++la]=0;memset(f,0,sizeof(f));for(int i=0;i<=9;i++)f[1][i][i]=1;for(int i=2;i<=lb;i++) for(int j=0;j<=9;j++)   {for(int k=0;k<=9;k++)     for(int p=0;p<=9;p++)f[i][j][p]+=f[i-1][k][p];    f[i][j][j]+=ff(i-1); }memset(vb,0,sizeof(vb));if(bx[lb])  for(int i=1;i<=bx[lb]-1;i++)    for(int j=0;j<=9;j++)vb[j]+=f[lb][i][j];    for(int i=lb-1;i;i--){for(int j=1;j<=9;j++) for(int k=0;k<=9;k++)vb[k]+=f[i][j][k]; for(int p=i+1;p<=lb;p++) for(int k=0;k<=bx[i]-1;k++)  vb[bx[p]]+=ff(i-1);if(bx[i])  for(int k=0;k<=bx[i]-1;k++)    for(int j=0;j<=9;j++)vb[j]+=f[i][k][j];}memset(va,0,sizeof(va));if(ax[la]) for(int i=1;i<=ax[la]-1;i++)  for(int j=0;j<=9;j++)va[j]+=f[la][i][j];for(int i=la-1;i;i--){for(int j=1;j<=9;j++) for(int k=0;k<=9;k++)va[k]+=f[i][j][k];for(int p=i+1;p<=la;p++) for(int k=0;k<=ax[i]-1;k++)  va[ax[p]]+=ff(i-1); if(ax[i])  for(int k=0;k<=ax[i]-1;k++)   for(int j=0;j<=9;j++)va[j]+=f[i][k][j];}for(int i=0;i<=9;i++)vb[i]-=va[i];printf("%lld",vb[0]);for(int i=1;i<=9;i++)printf(" %lld",vb[i]);printf("\n");return 0;}


0 0