hdu4352(数位dp+状态压缩)

来源:互联网 发布:miss淘宝店外设店 编辑:程序博客网 时间:2024/06/05 03:01

题意:

给出L和R找出在[L,R]中满足最长递增子序列长度等于K的个数。

题解:

状压想不到,看了kuangbin的才明白,1<<10状压存数出现了没有。利用了nlogn递增字序列算法的思想。

#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>#include<math.h>using namespace std;typedef long long lld;#define oo 0x3f3f3f3f#define mod 1000000007#define maxn 30+5lld dp[maxn][1<<10][15];int bit[maxn];lld L,R,K;int NextSt(int st,int x){    //找到第一个大于x的数并且替换他,nlogn求最长递增子序列的思想    for(int i=x;i<10;i++)        if(st&(1<<i)) return ((st^(1<<i))|(1<<x));    return st|(1<<x);}int GetLen(int st){    int cnt=0;    while(st)    {        if(st&1) cnt++;        st>>=1;    }    return cnt;}lld dfs(int pos,int st,int zero,int f){    if(pos<1) return GetLen(st)==K;    if(!f&&dp[pos][st][K]!=-1) return dp[pos][st][K];    int last= f ? bit[pos] : 9;    lld res=0;    for(int i=0;i<=last;i++)    {        res+=dfs(pos-1,(zero==0&&i==0)?0:NextSt(st,i),zero||i,f&&(i==last));    }    if(!f) dp[pos][st][K]=res;    return res;}lld GetAns(lld n){    int len=0;    while(n)    {        bit[++len]=n%10;        n/=10;    }    return dfs(len,0,0,1);}int main(){    int T;    memset(dp,-1,sizeof dp);    scanf("%d",&T);    for(int cas=1;cas<=T;cas++)    {        cin>>L>>R>>K;        cout<<"Case #"<<cas<<": "            <<GetAns(R)-GetAns(L-1)<<endl;    }return 0;}


0 0
原创粉丝点击