1591:数字计数

  • 0--9依次DP
  • 遇到当前i!=dig的时候也要继续dfs!!!
  • 最容易忽略的一点:l==0的时候要加特判
/*
reference:
    
Date:
    2019.10.08
sol:
    
*/
#include
using namespace std;
#define int long long
template inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;}
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dwn(i,a,b) for(int i=(a);i>=(b);--i)
#define mem(a,b) memset(a,b,sizeof(a))
#define ee(i,u) for(int i=head[u];i;i=e[i].next)

int l,r,len;
int dp[12+5][12*9+10];
int bit[12+5];

inline int dfs(int pos,int dig,int sum,int lead,int limit){
    if(pos>len)return sum;
    if(dp[pos][sum]!=-1 && !limit && !lead)return dp[pos][sum];
    int up=limit?bit[len-pos+1]:9;
    int res=0;
    rep(i,0,up){
        if(lead && i==0)
            res+=dfs(pos+1,dig,0,1,i==up && limit);
        else 
            res+=dfs(pos+1,dig,sum+(i==dig?1:0),0,i==up && limit)
            //不要把dig!=i的情况算漏掉了
    }
    if(!limit && !lead)dp[pos][sum]=res;
    return res;
}

inline int work(int x,int dig){
    mem(dp,-1);
    len=0;
    while(x){
        bit[++len]=x%10;
        x/=10;
    }
    return dfs(1,dig,0,1,1);
} 

#undef int 
int main(){
#define int long long
    #ifdef WIN32 
    freopen("test.txt","r",stdin);
    #endif
    rd(l),rd(r);
    if(l)
        rep(dig,0,9)
            printf("%lld ",work(r,dig)-work(l-1,dig));
    else 
        rep(dig,0,9)
            printf("%lld ",work(r,dig)-work(l,dig));
    return 0;
}

你可能感兴趣的:(1591:数字计数)