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

来源:互联网 发布:初学者怎么制作软件 编辑:程序博客网 时间:2024/04/30 01:30
传统数位dp思想,分位统计f[i][j][k]表示一个长i位的数第一位为j 到0 中字符k出现的次数。
#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>#include <cmath>#include <queue>using namespace std;long long f[13][10][10],fac[20];struct node{    long long a[10];}t1,t2;void init(){    fac[1]=1;for(int i=2;i<=13;i++) fac[i]=fac[i-1]*10;    for(int i=0;i<=9;i++) f[1][i][i]=1;    for(int i=2;i<=12;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]+=fac[i-1];            }        }    }}node get(long long x){    node ans;for(int i=0;i<=9;i++)ans.a[i]=0;    if(!x){ans.a[0]=1;return ans;}    int len=1;    for(;x>=fac[len];len++);    len--;    for(int i=1;i<len;i++)    {        for(int j=1;j<=9;j++)        {            for(int k=0;k<=9;k++)            {                ans.a[k]+=f[i][j][k];            }        }    }    ans.a[0]++;    int cur=x/fac[len];for(int i=1;i<cur;i++)        for(int j=0;j<=9;j++)            ans.a[j]=ans.a[j]+f[len][i][j];x%=fac[len];ans.a[cur]+=x+1;    for(int i=len-1;i;i--)    {        cur=x/fac[i];        for(int k=0;k<cur;k++)        for(int j=0;j<=9;j++)            ans.a[j]=ans.a[j]+f[i][k][j];        x%=fac[i];ans.a[cur]+=x+1;    }    return ans;}int main(){    init();    long long a,b;    cin>>a>>b;    t1=get(b);    t2=get(a-1);    for(int i=0;i<=9;i++){printf("%lld",t1.a[i]-t2.a[i]);if(i!=9)printf(" ");}    return 0;}

0 0