hdu 4352 数位dp+nlogn的LIS

题意:求区间L到R之间的数A满足A的的数位的最长递增序列的长度为K的数的个数。

链接:点我

该题的关键是记录LIS的状态,学习过nlogn解法的同学都知道,我们每次加入的元素要和前面的比对替换,这里就用了这个方法

比如1 3 6,用二进制表示为001000101,假如新加入的数为2,那么我们枚举比2大的数,观察是否存在,这里找到3,我们把3替换成2,状态变成1,2,6

不懂的童鞋可以看这里的nlogn的介绍:点我

还有就是注意前导0

 

 1 #include<cstdio>

 2 #include<iostream>

 3 #include<algorithm>

 4 #include<cstring>

 5 #include<cmath>

 6 #include<queue>

 7 #include<map>

 8 using namespace std;

 9 #define MOD 1000000007

10 typedef long long ll;

11 const int INF=0x3f3f3f3f;

12 const double eps=1e-5;

13 #define cl(a) memset(a,0,sizeof(a))

14 #define ts printf("*****\n");

15 const int MAXN=1005;

16 int n,m,tt,K;

17 ll dp[20][1<<11][11];

18 int digit[20];

19 int k;

20 ll getst(ll s,ll u,ll& xx)  // 状态转移

21 {

22     ll i,ss;

23     for(i=u;i<10;i++)

24     {

25         if(s&(1<<i)) break ;    //有比u大的,替换掉

26     }

27     if(i<10)

28     {

29         ss=s^(1<<i);

30         ss=ss^(1<<u);

31     }

32     else    //没有比u大的,u放入s中

33     {

34         xx++;

35         ss=s^(1<<u);

36     }

37     return ss;

38 }

39 ll dfs(int p,ll s,ll len,int fl,bool e) {    //位置,lis状态,lis长度,前导0

40     if (p==-1) return len==k;

41     if (!e &&dp[p][s][k]!=-1) return dp[p][s][k];

42     ll res = 0;

43     int u=e?digit[p]:9;

44     for (int i=0;i<=u;++i)

45     {

46         ll ns,nlen=len;

47         if(fl==0&&i==0) ns=0;

48         else    ns=getst(s,i,nlen);

49         res+=dfs(p-1,ns,nlen,fl||i!=0,e&&i==u);

50     }

51     return e?res:dp[p][s][k]=res;

52 }

53 ll solve(ll n)

54 {

55     int len=0;

56     while(n)

57     {

58         digit[len++]=n%10;

59         n/=10;

60     }

61     return dfs(len-1,0,0,0,1);

62 }

63 int main()

64 {

65     int i,j;

66     #ifndef ONLINE_JUDGE

67     freopen("1.in","r",stdin);

68     #endif

69     scanf("%d",&tt);

70     int ca=0;

71     memset(dp,-1,sizeof(dp));

72     while(tt--)

73     {

74         ll l,r;

75         scanf("%I64d%I64d%I64d",&l,&r,&k);

76         ll ans=solve(r)-solve(l-1);

77         printf("Case #%d: %I64d\n",++ca,ans);

78     }

79 }

 

你可能感兴趣的:(log)