HDU 4352 XHXJ's LIS(数位dp)

来源:互联网 发布:国内外手游推荐知乎 编辑:程序博客网 时间:2024/05/29 09:16

题意:寻找 [L,R] 中满足条件的数的数量。条件:把一个数看成字符串,它的LIS若等于k,则满足条件。

题解:数位dp。

一开始的想法:考虑nlogn的LIS写法,因此状态包含一个长度为10的字符串,由0~9,inf组成。

但是需要把字符串映射成int,用到map,复杂度据说太高了。

正解:nlogn的LIS写法是维护了一个数组,由0~9,inf组成。那么对于本题,我们只要用一个二进制维护出现的数字即可。

#include<cstdio>#include<string>#include<map>#include<iostream>#include<cstring>using namespace std;typedef long long ll;int k;ll l,r;int dig[20];ll d[20][1024][11];int nxtsta(int sta,int x) {for(int i=x;i<=9;++i) {if((sta>>i)&1) return (sta^(1<<i))|(1<<x);}return sta|(1<<x);}ll dp(int po,int sta,bool zero,bool limit) {if(po==-1) {int cnt=0;while(sta) {if(sta&1) ++cnt;sta>>=1;}return cnt==k;}if(!zero&&!limit&&d[po][sta][k]!=-1) return d[po][sta][k];int to=limit?dig[po]:9;ll ans=0;for(int i=0;i<=to;++i) {ans=ans+dp(po-1,(zero&&i==0)?0:nxtsta(sta,i),zero&&i==0,limit&&i==to);}if(!zero&&!limit) d[po][sta][k]=ans;return ans;}ll solve(ll x) {int pos=0;while(x) {dig[pos++]=x%10;x/=10;}return dp(pos-1,0,1,1);}int main() {///initmemset(d,-1,sizeof(d));int T;scanf("%d",&T);int ca=0;while(T--) {printf("Case #%d: ",++ca);///readscanf("%lld%lld%d",&l,&r,&k);///solveprintf("%lld\n",solve(r)-solve(l-1));}return 0;}


//下面代码把自己一开始的想法贴出来,因为我感觉可能是我写丑了...不一定是复杂度的问题

#include<cstdio>#include<string>#include<map>#include<iostream>#include<cstring>using namespace std;typedef long long ll;string s[2000];map<string,int> id;ll l,r;int k,cnts;int dig[25];ll d[25][15][2000];ll dp(int po,int ids,bool zero,bool limit) {//    cout<<po<<" "<<str<<" "<<endl;    string str=s[ids];    if(po==-1) return (k==10||str[k]=='A')&&str[k-1]!='A';    if(!zero&&!limit&&d[po][k][id[str]]!=-1) return d[po][k][id[str]];    int to=limit?dig[po]:9;    ll ans=0;    for(int i=0;i<=to;++i) {        string tmp=str;        for(int j=0;j<=9;++j) {            if(str[j]>='0'+i) {                if(!(zero&&i==0)) tmp[j]='0'+i;                break;            }        }        if(tmp[k]!='A') continue;        ans=ans+dp(po-1,id[tmp],zero&&i==0,limit&&i==to);    }    if(!zero&&!limit) d[po][k][id[str]]=ans;    return ans;    }ll solve(ll x) {    int pos=0;    while(x) {        dig[pos++]=x%10;        x/=10;    }    return dp(pos-1,1024,1,1);}void dfs(int po,int pre,string str) {    if(po==10) {        int len=str.length();        for(int i=len;i<=9;++i) str=str+'A';        s[++cnts]=str;        id[str]=cnts;        return ;    }    for(int i=pre+1;i<=9;++i) {        char c='0'+i;        dfs(po+1,i,str+c);    }    dfs(10,0,str);}int main() {    ///init    memset(d,-1,sizeof(d));    ///    cnts=0;    dfs(0,-1,"");    int T;scanf("%d",&T);    int ca=0;    while(T--) {        printf("Case #%d: ",++ca);        ///read        scanf("%lld%lld%d",&l,&r,&k);        ///solve        printf("%lld\n",solve(r)-solve(l-1));    }    return 0;}



0 0
原创粉丝点击