[BZOJ1833][ZJOI2010]数字计数

版权声明:欢迎转载(标记出处),写得不好还请多指教 https://blog.csdn.net/quan_tum/article/details/82146282

一道比较简单的数位dp题,记录每个数字出现个数。
把表示每个数字的那一维放到结构体里面了,方便一点。

#include<bits/stdc++.h>
#define ll long long
#define il inline 
char sr[1<<21],z[20];int C=-1,Z;
il void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
il void print(ll x){
    if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
    while(z[++Z]=x%10+48,x/=10);
    while(sr[++C]=z[Z],--Z);sr[++C]=' ';
}
struct A{
    ll n[10];
    A operator +(const A &other){
        A res;
        for(int i=0;i<=9;++i) res.n[i]=n[i]+other.n[i];
        return res;
    }
}f[13][10];
ll t[13],a,b;
void init(){
    t[1]=1;
    for(int i=2;i<=13;++i) t[i]=t[i-1]*10ll;
    for(int i=0;i<=9;++i) f[1][i].n[i]=1;
    for(int i=2,j,k;i<=12;++i)
    for(j=0;j<=9;++j)
    for(k=0;k<=9;++k)
    f[i][k]=f[i][k]+f[i-1][j],f[i][k].n[k]+=t[i-1];
}
il A calc(ll x){
    A ans;
    ans.n[0]=1;
    for(int i=1;i<=9;++i) ans.n[i]=0;
    if(!x) return ans;
    int l=log(x)/log(10)+1,h;
    for(int i=1;i<l;++i)
    for(int j=1;j<=9;++j) ans=ans+f[i][j];
    h=x/t[l],x%=t[l];
    for(int i=1;i<h;++i) ans=ans+f[l][i];
    ans.n[h]+=x+1;
    for(int i=l-1;i>0;--i){
        h=x/t[i],x%=t[i];
        for(int j=0;j<h;++j) ans=ans+f[i][j];
        ans.n[h]+=x+1;
    }return ans;
}
int main(){
    init();
    scanf("%lld%lld",&a,&b);
    A x=calc(a-1),y=calc(b);
    for(int i=0;i<=9;++i) print(y.n[i]-x.n[i]);
    Ot();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/quan_tum/article/details/82146282