hdu 4352 XHXJ's LIS 数位DP

数位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 }
View Code
原文地址:https://www.cnblogs.com/xin-hua/p/3325338.html