HDU-4352-数位dp,LIS

题目大意:求给定区间呢的数满足最长子序列长度为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;
} 



发布了193 篇原创文章 · 获赞 8 · 访问量 3万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章