C - Hasan and his lazy students(dp)

NCD2019

C - Hasan and his lazy students

题意: 给出n个序列,求最长的严格单调递增子序列的数目。( 1 ≤ n ≤ 1000 1\leq n \leq 1000 1n1000, 对结果取模 1 e 9 + 7 1e9 + 7 1e9+7)
思路:
需要先熟悉最长当单调子序列的dp求法。由数据范围可知,大概是个dp。这道题其实是用了两个一维dp数组。
dp[i]表示以第i个数结尾的最长单调递增子序列的长度
sum[i]表示前i个数中长度等于dp[i]的序列个数
代码:

const int N = 2e5 + 7, M = 1e6;
int a[1007];
int dp[1007], sum[1007], mod = 1000000007;
//dp[i]表示以第i个数结尾的最长单调子序列的长度
//sum[i]表示前i个数中长度等于dp[i]的序列个数

int main()
{
	IOS;
	int T; cin >> T;
	while (T--)
	{
		int n; cin >> n;
		for (int i = 1; i <= n; i++)
			cin >> a[i];
		
		int maxn = 0, ans = 0;
		for (int i = 1; i <= n; i++)
		{
			dp[i] = 1; sum[i] = 1;
			//二者都不能删,第一个删掉会导致dp[i] = 0(如果a[i]前面没有比a[i]小的)
			//第二个删掉会导致全程sum都是0
			for (int j = 1; j < i; j++)
				if (a[j] < a[i])
				{
					if (dp[j] + 1 > dp[i])
						dp[i] = dp[j] + 1, sum[i] = sum[j];
					else if (dp[j] + 1 == dp[i])
						sum[i] = (sum[i] + sum[j]) % mod;
				}
				
			if (dp[i] > maxn) maxn = dp[i], ans = sum[i];
			else if (dp[i] == maxn) ans = (ans + sum[i]) % mod;
		}
		
		cout << maxn << " " << ans << endl;
	}

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

to cling

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值