HPU第三次积分赛-D:Longest Increasing Subsequence(DP)

Longest Increasing Subsequence

描述

给出一组长度为n的序列,a1​,a2​,a3​,a4​...an​, 求出这个序列长度为k的严格递增子序列的个数

输入

第一行输入T组数据 T(0≤T≤10)
第二行输入序列大小n(1≤n≤100),长度k(1≤k≤n)
第三行输入n个数字ai​(0≤ai​≤1e9)

输出

数据规模很大, 答案请对1e9+7取模

输入样例 1 

2
3 2
1 2 2
3 2
1 2 3

输出样例 1

2
3

思路

用dp[i][j]数组记录在i位置,严格递增子序列长度为j的子序列的个数。

状态转移方程 :dp[i][j]=(dp[i][j]+dp[k][j-1])   

在每个i位置j长度的时候遍历前i的位置(不包括第i的位置),去寻找小于a[i]的数字,方案数变成当前i位置长度为j的个数+k位置长度为j-1的方案数

AC代码

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <limits.h>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <string>
#define ll long long
#define ms(a) memset(a,0,sizeof(a))
#define pi acos(-1.0)
#define INF 0x7f7f7f7f
const double E=exp(1);
const int maxn=1e3+10;
const int mod=1e9+7;
using namespace std;
int dp[maxn][maxn];//表示到第i个位置的递增子序列长度为j的个数
int a[maxn];
int main(int argc, char const *argv[])
{
	ios::sync_with_stdio(false);
	int t;
	int n,k;
	cin>>t;
	while(t--)
	{
		ms(dp);
		cin>>n>>k;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
			dp[i][1]=1;
		}
		for(int i=1;i<=n;i++)
		{
			for(int j=2;j<=i;j++)
			{
				for(int k=1;k<i;k++)
					// 如果a[i]>a[k],那么dp[i][j]的值加上在k位置的时候长度为j-1的值并取模
					if(a[i]>a[k])
						dp[i][j]=(dp[i][j]%mod+dp[k][j-1]%mod)%mod;
			}
		}
		int ans=0;
		for(int i=1;i<=n;i++)
			ans=(ans+dp[i][k])%mod;
		cout<<ans<<endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/wang_123_zy/article/details/81630698