题目描述 :给定一个整数数组 nums(长度 n ≤ 2000,元素范围 -10^6 ~ 10^6),求最长严格递增子序列 的个数。若最长递增子序列长度为 L,输出长度为 L 的不同子序列个数(下标不同即视为不同)。
输入:
-
第一行:
n -
第二行:
n个整数
输出:最长递增子序列的个数。
示例:
text
输入:
5
1 3 5 4 7
输出:
2
解释:最长递增子序列长度为 4,有两个:1 3 5 7 和 1 3 4 7。
解题思路
维护两个数组:
-
dp[i]:以nums[i]结尾的最长递增子序列长度。 -
cnt[i]:以nums[i]结尾的最长递增子序列个数。
转移:
-
若
nums[j] < nums[i]:-
若
dp[j] + 1 > dp[i]:dp[i] = dp[j] + 1,cnt[i] = cnt[j] -
若
dp[j] + 1 == dp[i]:cnt[i] += cnt[j]
-
最后统计所有 dp[i] == L 的 cnt[i] 之和。
参考代码
c
#include <stdio.h>
int main(void) {
int n;
scanf("%d", &n);
int nums[2005];
for (int i = 0; i < n; i++) scanf("%d", &nums[i]);
int dp[2005];
long long cnt[2005]; // 个数可能较大,用 long long
for (int i = 0; i < n; i++) {
dp[i] = 1;
cnt[i] = 1;
}
int maxLen = 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
if (nums[j] < nums[i]) {
if (dp[j] + 1 > dp[i]) {
dp[i] = dp[j] + 1;
cnt[i] = cnt[j];
} else if (dp[j] + 1 == dp[i]) {
cnt[i] += cnt[j];
}
}
}
if (dp[i] > maxLen) maxLen = dp[i];
}
long long ans = 0;
for (int i = 0; i < n; i++) {
if (dp[i] == maxLen) ans += cnt[i];
}
printf("%lld\n", ans);
return 0;
}