您的位置:首页 > 其它

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

2015-07-22 15:38 351 查看
最长递增子序列很自然就想到二分(nlogn)的算法,用状态S存储二分后的答案,第i位为1就是i存在于二分的答案中。

注意前导0。

我的代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>

using namespace std;
typedef __int64 LL;
const int inf = 0x3f3f3f3f;

LL dp[20][1<<10][11],l,r,k;
LL bit[20],top;
int tm[20];

int get_news(int s,int d){
fill(tm,tm+20,inf);
int i,j;
for(i=0,j=0;i<10;i++) if(s>>i&1) tm[j++] = i;
*lower_bound(tm,tm+20,d) = d;
int news = 0;
for(i=0;i<10;i++) if(tm[i]!=inf) news |= (1 << tm[i]);
return news;
}

int cnt(int s){
int res = 0,i;
for(i=0;i<10;i++) if(s>>i&1) res++;
return res;
}

LL dfs(int i,int s,bool e,bool z){
if(i == -1) return cnt(s) == k ? 1LL : 0;
if(!e&&dp[i][s][k] != -1) return dp[i][s][k];
LL res = 0;
int d,u = e ? bit[i] : 9;
for(d = 0 ; d <= u ; d++){
res += dfs(i-1,z&&(d==0) ? 0 : get_news(s,d),e&&(d==u),z&&(d==0));
}
return e?res:dp[i][s][k]=res;
}

LL solve(LL n){
top = 0;
for(;n;n/=10) bit[top++] = n%10;
return dfs(top-1,0,1,1);
}

int main(){
int cas;
scanf("%d",&cas);
memset(dp,-1,sizeof(dp));
for(int T=1;T<=cas;T++){
scanf("%I64d%I64d%I64d",&l,&r,&k);
printf("Case #%d: %I64d\n",T,solve(r)-solve(l-1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: