数字计数(数位dp)
细节见代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 20; 5 const int mod = 1e9+7; 6 7 ll l,r; 8 int a[15]; 9 ll dp[15][10][15];//dp[pos][num][sum]:位pos 之前当前num字符已经出现sum次 10 11 ll dfs(int pos,int num, ll sum, bool lead,bool limit){ 12 13 if( !pos ) return sum; 14 if( !limit&&!lead&& dp[pos][num][sum]!=-1 ) return dp[pos][num][sum]; 15 int up = limit?a[pos]:9; 16 ll ans=0; 17 18 for(int i=0;i<=up;i++){ 19 if( i==0 ){ 20 if( !lead || pos==1 ) ans += dfs(pos-1,num,sum+(num==i),0,limit&&i==up);//此位的0非前导0 21 else ans += dfs(pos-1,num,sum,1,limit&&i==up);//此位的0是前导0 22 }else{ 23 ans += dfs(pos-1,num,sum+(num==i),0,limit&&(i==up)); 24 } 25 } 26 return ( (!limit)&&(!lead))?dp[pos][num][sum]=ans:ans; 27 } 28 29 ll solve(ll x,int num){ 30 a[0] = 0; 31 if( !x ) return num==0?1:0;//注意这里 32 while( x ) a[++a[0]]=x%10, x/=10; 33 return dfs(a[0],num,0,1,1); 34 } 35 36 int main() 37 { 38 memset(dp,-1,sizeof(dp)); 39 scanf("%lld%lld",&l,&r); 40 for(int i=0;i<=8;i++){ 41 printf("%lld ",solve(r,i)-solve(l-1,i)); 42 } 43 printf("%lld\n",solve(r,9)-solve(l-1,9)); 44 return 0; 45 }