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

 

posted @ 2013-05-21 19:25  诺小J  阅读(373)  评论(0编辑  收藏  举报