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

来源:互联网 发布:最新网络语 编辑:程序博客网 时间:2024/05/20 22:28

最长递增子序列很自然就想到二分(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;}


0 0
原创粉丝点击