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

 

转载于:https://www.cnblogs.com/jie-dcai/p/4286777.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值