数位DP!
dp[i][j][k]:第i位数,状态为j,长度为k
代码如下:
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 #include<iomanip> 5 #include<cmath> 6 #include<cstring> 7 #include<vector> 8 #define ll __int64 9 using namespace std; 10 ll dp[20][1025][11]; 11 int bit[20],k; 12 int Getlen (int sta)//求出最长上升子序列的长度 13 { 14 int ret = 0; 15 while (sta) 16 { 17 ret += (sta&1); 18 sta >>= 1; 19 } 20 return ret; 21 } 22 23 int Getnew(int x , int sta)//更新当前数的最长上升子序列的状态 24 { 25 int i; 26 for (i = x ; i <= 9 ; i++) 27 if ((sta & (1<<i))) 28 return (sta-(1<<i))|(1<<x); 29 return sta|(1<<x); 30 } 31 ll dfs(int pos,int s,bool z,bool f) 32 { 33 if(pos==-1) return Getlen(s)==k; 34 if(!f&&dp[pos][s][k]!=-1) return dp[pos][s][k]; 35 ll ans=0; 36 int e=f?bit[pos]:9; 37 for(int i=0;i<=e;i++){ 38 ans+=dfs(pos-1,(z&&i==0)?0:Getnew(i,s),z&&i==0,f&&i==e); 39 } 40 if(!f&&dp[pos][s][k]==-1) dp[pos][s][k]=ans; 41 return ans; 42 } 43 ll cal(ll n) 44 { 45 int m=0; 46 while(n){ 47 bit[m++]=n%10; 48 n/=10; 49 } 50 return dfs(m-1,0,1,1); 51 } 52 int main() 53 { 54 int t,i,j,ca=0; 55 ll a,b; 56 scanf("%d",&t); 57 memset(dp,-1,sizeof(dp)); 58 while(t--){ 59 scanf("%I64d%I64d%d",&a,&b,&k); 60 printf("Case #%d: %I64d ",++ca,cal(b)-cal(a-1)); 61 } 62 return 0; 63 }