hdu 4352 统计数字数位上最长上升子序列长度为k的个数

题意:

1245 这个数属于上升长度为4的数字,1213这个数字属于上升长度为3的数字。

统计区间[l,r]中上升长度为k的数字个数。

State 状态压缩,表示最长上升的序列用到的数字有哪些

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 typedef long long LL;
 6 int const N = 22;
 7 int const M = 1030;
 8 int bit[N],ln,pow2[11],k;
 9 LL dp[N][M][20];
10 void pre()
11 {
12      pow2[0]=1;
13      for(int i=1;i<=10;i++)pow2[i]=(pow2[i-1]<<1);
14 }
15 LL getsum1(int t,int limit,int len,int state)
16 {
17    if(!t)return (len==k);
18    if(!limit&&dp[t][state][k]!=-1)return dp[t][state][k];
19    int up=(limit?bit[t]:9);
20    LL ans=0;
21    for(int i=0;i<=up;i++)
22    {
23        if(state||i)
24        {
25           if(pow2[i]>state)
26           {
27              ans+=getsum1(t-1,limit&&i==up,len+1,state|pow2[i]);
28           }
29           if(pow2[i]&state)
30           {
31              ans+=getsum1(t-1,limit&&i==up,len,state);
32           }
33           else
34           {
35              for(int j=i+1;j<=9;j++)
36              {
37                  if(state&pow2[j])
38                  {
39                     ans+=getsum1(t-1,limit&&i==up,len,state^pow2[j]|pow2[i]);
40                     break;
41                  }
42              }
43           }
44        }
45        else
46        {
47           ans+=getsum1(t-1,limit&&i==up,0,0);
48        }
49    }
50    if(!limit)dp[t][state][k]=ans;
51    return ans;
52 }
53 LL getsum2(LL n)
54 {
55    if(n==0)return 0;
56    for(ln=0;n;bit[++ln]=n%10,n/=10);
57    return getsum1(ln,1,0,0);
58 }
59 int main()
60 {
61     pre();
62     memset(dp,-1,sizeof(dp));
63     int T,t=0;
64     k=2;
65     scanf("%d",&T);
66     while(T--)
67     {
68           LL l,r;
69           scanf("%I64d %I64d",&l,&r);
70           scanf("%d",&k);
71           l--;
72           printf("Case #%d: %I64d\n",++t,getsum2(r)-getsum2(l));
73     }
74     return 0;
75 }
View Code

 

转载于:https://www.cnblogs.com/nuoyan2010/archive/2013/05/21/3091321.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值