luoguP2602 [ZJOI2010]数字计数 数位dp

数位dp.  

细节真的很多.  

1. 考虑清楚每个数的贡献. 

2. 0 特殊考虑. 

code: 

#include <bits/stdc++.h>   
#define ll long long 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;  
// 令 f[i][j][k]      
ll f[20][20][20],bin[20];   
int num[20],cnt; 
ll b[20];   
void init() 
{
    bin[0]=1;  
    for(int i=1;i<13;++i)    bin[i]=bin[i-1]*10;   
    for(int i=0;i<10;++i)    f[1][i][i]=1;     
    for(int i=2;i<13;++i)    
    {
        for(int j=0;j<10;++j)      
            for(int k=0;k<10;++k)   
            {
                f[i][j][k]=(j==k)*bin[i-1];   
                for(int l=0;l<10;++l)  
                    f[i][j][k]+=f[i-1][l][k];       
            }
    }             
}      
ll calc(ll x,int t) 
{ 
    memset(num,0,sizeof(num)),cnt=0;  
    do 
    {  
        num[++cnt]=x%10;  
        x/=10;  
    }while(x);     
    ll ans=0; 
    for(int i=1;i<cnt;++i) 
        for(int j=1;j<10;++j)   
            ans+=f[i][j][t];    
    b[0]=0; 
    for(int i=1;i<=cnt;++i) b[i]=num[i]*bin[i-1]+b[i-1];   
    for(int i=cnt;i>=1;--i) 
    {
        for(int j=1;j<num[i];++j) ans+=f[i][j][t];      
        if(i!=cnt&&num[i]!=0)  ans+=f[i][0][t];              
        if(i>1&&num[i]==t&&b[i-1]) ans+=b[i-1];       
    }  
    return ans;   
}
int main() 
{ 
    // setIO("input");    
    init();   
    ll L,R;   
    scanf("%lld%lld",&L,&R);       
    for(int i=0;i<10;++i)  
        printf("%lld ",calc(R+1,i)-calc(L,i));  
    return 0; 
}

  

posted @ 2020-06-12 08:43  EM-LGH  阅读(160)  评论(0编辑  收藏  举报