程序员人生 网站导航

[数位dp+状态压缩] hdu 4352 XHXJ's LIS

栏目:互联网时间:2014-10-13 00:13:40

题意:

给x、y、k,在[x,y] 范围内最长上升子序列长度是k的数有几个

思路:

模仿 LIS nlogn的想法,这里就只有10个数,进行状压

然后直接搜就好了不用二分

然后按位dp下去就ok了!

代码:

#include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"queue" #include"algorithm" #include"iostream" using namespace std; //2014年9月26日09:46:04 __int64 dp[22][1024][11]; int num[22]; struct node { int n,l; }; node js(int n,int x,int tep) { node ans; ans.l=tep; int i; for(i=x; i<10; i++) if(n&(1<<i)) break; if(i==10) //没找到 长度加一 填上那个数 { ans.l=tep+1; n|=(1<<x); } else //找到 更新那个数 { n^=(1<<i); n|=(1<<x); } ans.n=n; return ans; } __int64 dfs(int site,int n,int l,int k,int zero,int f) { if(site==0) { if(zero) return 0; return l==k; } if(!f&&!zero&&~dp[site][n][k]) return dp[site][n][k]; int len=f?num[site]:9; __int64 ans=0; for(int i=0; i<=len; i++) { node tep; if(zero) { if(i==0) ans+=dfs(site-1,n,l,k,zero&&i==0,f&&i==len); else { tep=js(n,i,l); ans+=dfs(site-1,tep.n,tep.l,k,zero&&i==0,f&&i==len); } } else { tep=js(n,i,l); ans+=dfs(site-1,tep.n,tep.l,k,zero&&i==0,f&&i==len); } } if(!f&&!zero) dp[site][n][k]=ans; return ans; } __int64 solve(__int64 x,int k) { int cnt=0; while(x) { num[++cnt]=x%10; x/=10; } return dfs(cnt,0,0,k,1,1); } int main() { int t,cas=1; cin>>t; memset(dp,-1,sizeof(dp)); while(t--) { __int64 x,y; int k; scanf("%I64d%I64d%d",&x,&y,&k); printf("Case #%d: %I64d ",cas++,solve(y,k)-solve(x-1,k)); } return 0; } //2014年9月26日10:24:07


------分隔线----------------------------
------分隔线----------------------------

最新技术推荐