HDU 4352

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <string.h>
 5 #include <algorithm>
 6 #define LL __int64
 7 using namespace std;
 8 
 9 LL dp[25][1<<10][11];
10 LL aa,bb;
11 int a[30],k;
12 /*这道题的难点就在于DP的状态表示了,确实是这样的。DP【pos】【state】【K】,pos表示当前的数位,state表示当前的LIS的状态,K
13 表示要求的K长度。那个DFS就不解释了,都成模板了。而对于state的转移,是用二进制表示当前状态,因为最长的
14 序列就是0~9十个数表示,所以有十位的二进制。例如12456的上升序列,下一次出现3,则可表示为12356,至于转移,要联系nlogn解法的
15 LIS来看了 */ 
16 int getnews(int x,int s){
17     for(int i=x;i<10;i++)
18         if(s&(1<<i))return (s^(1<<i))|(1<<x);
19     return s|(1<<x);
20 }
21 int getnum(int s){
22     int ret=0;
23     while(s)
24     {
25         if(s&1)ret++;
26         s>>=1;
27     }
28     return ret;
29 }
30 
31 LL dfs(int len,int st,bool zero,bool flag){
32     if(len==0) return getnum(st)==k;
33     if(!flag&&dp[len][st][k]!=-1)
34     return dp[len][st][k];
35     int en=flag?a[len]:9;
36     LL ans=0;
37     for(int i=0;i<=en;i++){    
38         ans+=dfs(len-1,(zero&&i==0)?0:getnews(i,st),zero&&i==0,flag&&i==en);
39     }
40     if(!flag) dp[len][st][k]=ans;
41     return ans;
42 }
43 
44 LL cal(LL n){
45     LL tmp=n;
46     int len=0;
47     while(tmp){
48         a[++len]=(int)(tmp%10);
49         tmp/=10;
50     }
51     return dfs(len,0,true,true);
52 }
53 
54 int main(){
55     memset(dp,-1,sizeof(dp));
56     int T,t=0;
57     scanf("%d",&T);
58     while(++t<=T){
59         scanf("%I64d%I64d%d",&aa,&bb,&k);
60         printf("Case #%d: %I64d\n",t,cal(bb)-cal(aa-1LL));
61     }
62     return 0;
63 }
View Code

 

posted @ 2015-02-11 18:22  chenjunjie1994  阅读(248)  评论(0编辑  收藏  举报