1. 问题描述:
给定一个序列 (a_1, a_2, …, a_n), 它的一个上升子序列是指从序列中取出一些元素,按照原来的顺序排列后,是单调递增的序列。
例如,对于序列 (3, 2, 7, 6, 7),取出下标为 2, 4, 5 的元素 a_2, a_4, a_5,即 2, 6, 7,是一个上升子序列。
在这个序列中,有 7 个长度为 2 的上升子序列,
例如
1. 下标 1, 3 对应的 3, 7;
2. 下标 1, 4 对应的 3, 6;
3. 下标 1, 5 对应的 3, 7;
4. 下标 2, 3 对应的 2, 7;
5. 下标 2, 4 对应的 2, 6;
6. 下标 2, 5 对应的 2, 7;
7. 下标 4, 5 对应的 6, 7。
注意,可能有下标不同但对应数值相同的上升子序列,他们应当算成不同的上升子序列。
给定序列,请问序列中一共有多少个长度为 k 的上升子序列。
输入格式
输入第一行包含两个整数 n, k,表示序列的长度和上升子序列的长度。
第二行包含 n 个整数 a_1, a_2, …, a_n,表示给定的序列。
输出格式
输出一行,包含一个整数,表示长度为 k 的上升子序列的数量,答案可能很大,请输出答案除以 1000007 的余数。
样例输入
5 2
3 2 7 6 7
样例输出
7
数据规模和约定
对于 30% 的评测用例,1 <= n <= 20, 0 <= a_i <= 100。
对于 50% 的评测用例,1 <= n <= 100, 0 <= a_i <= 1000。
对于所有评测用例,1 <= n <= 1000, 1 <= k <= 10, 0 <= a_i <= 10000。
2. 思路分析:
上升子序列的问题是经典的动态规划问题,一般求解上升子序列的问题中dp数组的含义是以nums[i]结尾的上升子序列的长度,因为这道题目需要求解的是长度为k的上升子序列的数目,所以我们可以在一维dp数组上增加多一维那么就可以表示以nums[i]结尾长度为k的上升子序列的数目,明确dp数组的含义之后接下来就好办了,使用三层循环进行dp数组的推导即可,最外层循环表示以当前的nums[i]结尾,第二层循环是通过尝试将nums[i]拼接到已经有的上升子序列后面构成更长的上升子序列,最后一个循环是用来计算以nums[i]结尾长度为(1...k)的上升子序列的数目
3. 代码如下:
if __name__ == '__main__':
n, k = map(int, input().split())
nums = list(map(int, input().split()))
dp = [[0] * (k + 1) for i in range(n)]
# 以nums[i]结尾长度为1的dp数组的数目
for i in range(n):
dp[i][1] = 1
for i in range(n):
for j in range(i):
if nums[i] > nums[j]:
# 以nums[i]结能够构成更长的上升子序列
for k in range(2, k + 1):
# 在长度为k-1的基础上以当前的nums[i]结尾那么长度就变成了k
dp[i][k] = (dp[i][k] + dp[j][k - 1]) % 1000007
count = 0
for i in range(n):
count = (count + dp[i][k]) % 1000007
print(count)