蓝桥杯12届选拔赛3期-10题
问题描述
给定一个序列 (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, 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。
思路:上升子序列,然后看了一下数据最大n为1000 多半来说就是动态规划了。
#include<iostream>
using namespace std;
#include<cstring>
const int N = 1010;
int n , k , a[N];
int dp[N][N]; // dp[i][j]以i结尾 长度为 j的 上升子序列数量
int main()
{
cin>> n>> k ;
for(int i = 1 ; i <= n ; i++)cin>> a[i]; //这里从1开始的
memset(dp , 0 ,sizeof dp);
for(int i = 1 ; i <= n ; i++)dp[i][1]=1; // 初始化 ,长度为1的只有本身即为1
for(int i = 1 ; i <= n ; i++){
for(int j = 1 ; j <= k ; j++){
int cnt = 0;
for(int z = 1 ; z <= i ; z++){
if(a[i] > a[z])dp[i][j] += dp[z][j-1];
//以i结尾长度为j的 可以由0~i-1 ,j-1 的得到 ,只要其满足上升就行
}
}
}
int ans = 0;
for(int i = 1 ; i <= n ; i++)
{
ans += dp[i][k] ;//把所有长度k相加 为答案;
ans %=1000007 ;
}
cout<<ans;
return 0;
}
相关题
acwing社区:acwing.895,11届蓝桥杯c++b组国赛第4题,需要的我私聊发你
总结
可能有更好的解法,欢迎大佬评论区喷我。