题面
给定一段时间内股票的每日售价(正16位整数)。
你可以选择在任何一天购买股票。
每次你选择购买时,当前的股票价格必须严格低于你之前购买股票时的价格。
编写一个程序,确定你应该在哪些天购进股票,可以使得你能够购买股票的次数最大化。
例如,下面是一个股票价格时间表:
Day 1 2 3 4 5 6 7 8 9 10 11 12
Price 68 69 54 64 68 64 70 67 78 62 98 87
如果每次购买都必须遵循当前股票价格严格低于之前购买股票时的价格,那么投资者最多可以购买四次该股票。
买进方案之一为:
Day 2 5 6 10
Price 69 68 64 62
输入格式
第1行包含整数 N,表示给出的股票价格的天数。
第2至最后一行,共包含 N 个整数,每行10个,最后一行可能不够10个,表示 N 天的股票价格。
同一行数之间用空格隔开。
输出格式
输出占一行,包含两个整数,分别表示最大买进股票次数以及可以达到最大买进次数的方案数。
如果两种方案的买入日序列不同,但是价格序列相同,则认为这是相同的方案(只计算一次)。
数据范围
1≤N≤5000
输入样例1:
12
68 69 54 64 68 64 70 67 78 62
98 87
输出样例1:
4 2
输入样例2:
5
4 3 2 1 1
输出样例2:
4 1
题解
dp不是问题, 那就难再计数上, 那就先考虑重复问题
对于以第i天结尾的a序列, 以第j天结尾的b序列, 且(i < j 且a,b都为最长序列)
如果 x[i] > x[j] 那么a序列还能再加上第j天,那么a,b都为最长序列则矛盾
如果 x[i] < x[j] 那么a序列和b序列绝对不会重复,所以不需要讨论
如果 x[i] == x[j] 那么j为结尾的b序列的计数中必然包含a序列
eg x[i - n] x[i - n + 1] ... x[i] 构成序列a
那么必然 x[i - n] x[i - n + 1] .. x[j]构成序列b
则必然会出现重复,干脆出现 x[i] == x[j] 时,就把 cnt[i] = 0 直接清零, 则cnt[j] 包含着a序列的计数
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5001;
int n, a[maxn], f[maxn], cnt[maxn];
int mx, ans;
int main()
{
cin >> n;
for (int i = 1; i <= n; ++i)
{
cin >> a[i]; f[i] = 1;
for (int j = 1; j < i; ++j)
if (a[j] > a[i]) f[i] = max(f[i], f[j] + 1);
for (int j = 1; j < i; ++j)
if (a[j] > a[i] && f[i] == f[j] + 1) cnt[i] += cnt[j];
else if (a[i] == a[j]) cnt[j] = 0;
if (cnt[i] == 0) cnt[i] = 1; //即长度为1, cnt[i]初始化为1
}
for (int i = 1; i <= n; ++i)
if (f[i] == mx) ans += cnt[i];
else if (f[i] > mx) mx = f[i], ans = cnt[i];
cout << mx << ' ' << ans;
return 0 ;
}