hdu 4352 XHXJ's LIS 数位DP+最长上升子序列

题目描述

#define xhxj (Xin Hang senior sister(学姐))
If you do not know xhxj, then carefully reading the entire description is very important.
As the strongest fighting force in UESTC, xhxj grew up in Jintang, a border town of Chengdu.
Like many god cattles, xhxj has a legendary life:
2010.04, had not yet begun to learn the algorithm, xhxj won the second prize in the university contest. And in this fall, xhxj got one gold medal and one silver medal of regional contest. In the next year's summer, xhxj was invited to Beijing to attend the astar onsite. A few months later, xhxj got two gold medals and was also qualified for world's final. However, xhxj was defeated by zhymaoiing in the competition that determined who would go to the world's final(there is only one team for every university to send to the world's final) .Now, xhxj is much more stronger than ever,and she will go to the dreaming country to compete in TCO final.
As you see, xhxj always keeps a short hair(reasons unknown), so she looks like a boy( I will not tell you she is actually a lovely girl), wearing yellow T-shirt. When she is not talking, her round face feels very lovely, attracting others to touch her face gently。Unlike God Luo's, another UESTC god cattle who has cool and noble charm, xhxj is quite approachable, lively, clever. On the other hand,xhxj is very sensitive to the beautiful properties, "this problem has a very good properties",she always said that after ACing a very hard problem. She often helps in finding solutions, even though she is not good at the problems of that type.
Xhxj loves many games such as,Dota, ocg, mahjong, Starcraft 2, Diablo 3.etc,if you can beat her in any game above, you will get her admire and become a god cattle. She is very concerned with her younger schoolfellows, if she saw someone on a DOTA platform, she would say: "Why do not you go to improve your programming skill". When she receives sincere compliments from others, she would say modestly: "Please don’t flatter at me.(Please don't black)."As she will graduate after no more than one year, xhxj also wants to fall in love. However, the man in her dreams has not yet appeared, so she now prefers girls.
Another hobby of xhxj is yy(speculation) some magical problems to discover the special properties. For example, when she see a number, she would think whether the digits of a number are strictly increasing. If you consider the number as a string and can get a longest strictly increasing subsequence the length of which is equal to k, the power of this number is k.. It is very simple to determine a single number’s power, but is it also easy to solve this problem with the numbers within an interval? xhxj has a little tired,she want a god cattle to help her solve this problem,the problem is: Determine how many numbers have the power value k in [L,R] in O(1)time.
For the first one to solve this problem,xhxj will upgrade 20 favorability rate。

Input

First a integer T(T<=10000),then T lines follow, every line has three positive integer L,R,K.(0<L<=R<2 63-1 and 1<=K<=10).

Output

For each query, print "Case #t: ans" in a line, in which t is the number of the test case starting from 1 and ans is the answer.

Sample Input

1
123 321 2

Sample Output

Case #1: 139 

分析

一句话题意:给你L到R区间,和一个数字K,然后让你求L到R区间之内满足最长上升子序列长度为K的数字有多少个

看到题目,显然是数位DP,套板子就可以

如果你不会打板子,点击这里

如果你知道板子怎么写,从这里开始读

首先我们要定义f数组

第一维显然是枚举到的数位,第二维要存储现在的状态,也就是到上一位最长上升子序列的长度

第三维是你想要达到的状态,也就是题目中的k值(都是套路

然后其它的就是板子了,但是要注意几个问题

1、写代码的时候要考虑前缀零,否则会对结果造成影响

比如你可能把012看成一个长度为3的上升子序列,而实际长度为2

2、求最长上升子序列需要好好思考一下

如果我们把每次遍历到的数存在一个数组里,会比较麻烦,而且时间效率也不优秀

所以我们考虑状态压缩

我们用一个长度为10的二进制数表示数字几有没有被选到

如果为0,则表明该位对应的数字是最长上升子序列的一部分,反之则不是

每次遍历时,如果新加入的数是最大的,我们就直接把该数代表的位置置为1就可以

如果新加入的数不是最大的,我们就把第一个小于等于该位的数置为0,把新加入的位数置为1

统计长度时只要看有几个1就可以了

比如325687

我们第一次加了一个3,3是最大的,状态就变成0001000000

第二次我们加了一个2,我们就把3所在的那一位置为0,把2的这一位置为1,状态变为0010000000

同样地,加5,变成0010010000,加6,变成0010011000

加8,变成0010011010,加7,变成0010011100

最后的结果就是4,其实和二分法求最长上升子序列是一样的

代码

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<queue>
 6 #include<cmath>
 7 using namespace std;
 8 typedef long long ll;
 9 ll f[25][1<<11][25],num[30];
10 ll a,b,k;
11 ll upda(ll x,ll s){
12     for(ll i=x;i<=9;i++){
13         if(s&(1<<i)) return (s^(1<<i)|(1<<x));
14     }
15     return (s|(1<<x));
16 }
17 ll getans(ll x){
18     ll ans=0;
19     while(x){
20         if(x&1) ans++;
21         x>>=1;
22     }
23     return ans;
24 }
25 ll asd(ll now,ll zt,ll lim,ll jzer){
26     if(now<0){
27         if(getans(zt)==k) return 1;
28         else return 0;
29     }
30     if(f[now][zt][k]!=-1 && lim==0 && !jzer){
31         return f[now][zt][k];
32     }
33     ll mmax=9;
34     if(lim==1) mmax=num[now];
35     ll anss=0;
36     for(ll i=0;i<=mmax;i++){
37         anss+=asd(now-1,(jzer&(i==0))?0:upda(i,zt),lim&&(i==mmax),jzer&(i==0));
38     }
39     if(!lim && !jzer) f[now][zt][k]=anss;
40     return anss;
41 }
42 ll solve(ll xx){
43     ll cnt=0;
44     memset(num,0,sizeof(num));
45     while(xx){
46         ll aa=xx%10;
47         num[cnt++]=aa;
48         xx/=10;
49     }
50     return asd(cnt-1,0,1,1);
51 }
52 int main(){
53     ll t;
54     cin>>t;
55     memset(f,-1,sizeof(f));
56     ll js=0;
57     while(t--){
58         cin>>a>>b>>k;
59         ll ans=solve(b)-solve(a-1);
60         cout<<"Case #"<<++js<<": "<<ans<<endl;
61     }
62     return 0;
63 }
View Code

猜你喜欢

转载自www.cnblogs.com/liuchanglc/p/12750816.html