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\n",++ca,cal(b)-cal(a-1));

61       }

62     return 0;

63 }
View Code

 

 

 

你可能感兴趣的:(HDU)