HDU 4352 XHXJ's LIS(数位DP+LIS+状态压缩)

来源:互联网 发布:影梭本地端口 编辑:程序博客网 时间:2024/05/20 23:31

题意:给出一个区间,求这个区间内把数字看成字符串后最长上升子序列(可以不连续)为k的个数。

思路:可以用类似求lis的方法来做,因为k最大只有10,而且lis中的g数组是递增的,g的值只有可能取0到9,所以我们可以用状态压缩表示当前g数组中0到9是否出现,然后在数位dp的时候计算状态即可。

#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<iostream>#include<algorithm>#include<vector>#include<map>#include<queue>#include<stack>#include<string>#include<map>#include<set>#include<ctime>#define eps 1e-6#define LL long long#define pii pair<int, int>//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;//const int MAXN = 5000000 + 5;//const int INF = 0x3f3f3f3f;int n, digit[20], k;LL dp[20][20][1<<10];int getNum(int s) {int ans = 0;for(int i = 0; i < 10; i++) if((1<<i) & s) ans++;return ans;}int update(int x, int s) {for(int i = x; i < 10; i++) if((1<<i)&s) return s^(1<<i)|(1<<x);return s|(1<<x);}LL dfs(int len, int s, bool same, bool top) {if(!len) return getNum(s) == k;if(!same && !top && dp[k][len][s]!=-1) return dp[k][len][s];int maxd = same ? digit[len] : 9;LL ans = 0;for(int i = 0; i <= maxd; i++) {if(top && !i) ans += dfs(len-1, s, 0, 1);else ans += dfs(len-1, update(i, s), same&&i==maxd, 0);}if(!same && !top) dp[k][len][s] = ans;return ans;}LL solve(LL num) {int len = 0;while(num) {digit[++len] = num % 10;num /= 10;}return dfs(len, 0, 1, 1);}int main() {    //freopen("input.txt", "r", stdin);memset(dp, -1, sizeof(dp));int T, kase = 0;cin >> T;while(T--) {                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             LL le, ri;scanf("%I64d%I64d%d", &le, &ri, &k);LL ans = solve(ri) - solve(le-1);printf("Case #%d: %I64d\n", ++kase, ans);}    return 0;}

0 0
原创粉丝点击