HDU-4352-数位dp,LIS

来源:互联网 发布:淘宝小店描述怎么写 编辑:程序博客网 时间:2024/05/17 22:10

题目大意:求给定区间呢的数满足最长子序列长度为k;

题目解析:LIS,dp第二维表示当前的序列,第三维表示目标长度为k,dfs的时候更新序列的时候要像LIS一样找到>=i的第一位并且去掉然后加上第i位;

AC代码:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>using namespace std;typedef long long ll;ll dp[20][1<<10][20],num[20];int getbit(int x){int ans=0;while(x){if(x&1)ans++;x>>=1;}return ans;}int k;int update(int x,int s){for(int i=x;i<=9;i++){if(s&(1<<i)){return (s^(1<<i))|(1<<x); }}return s|(1<<x); }ll dfs(int pos,int s,bool lead,bool limit){if(pos==-1)return getbit(s)==k;if(!lead&&!limit&&dp[pos][s][k]!=-1)return dp[pos][s][k];int u=limit?num[pos]:9;ll ans=0;for(int i=0;i<=u;i++){if(lead&&i==0)ans+=dfs(pos-1,0,true,limit&&i==u);else  ans+=dfs(pos-1,update(i,s),lead&&(i==0),limit&&(i==u));}if(!lead&&!limit)return dp[pos][s][k]=ans;return ans;}ll solve(ll n){int cnt=0;while(n){num[cnt++]=n%10;n/=10;}return dfs(cnt-1,0,true,true);}int main(){int cas,c=1;memset(dp,-1,sizeof(dp));scanf("%d",&cas);while(cas--){ll a,b;scanf("%lld%lld%d",&a,&b,&k);printf("Case #%d: ",c++);printf("%lld\n",solve(b)-solve(a-1));}return 0;} 



0 0
原创粉丝点击