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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章