1. 程式人生 > 實用技巧 >數字計數(數位dp)

數字計數(數位dp)

數字計數(數位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 }