蓝桥杯12届选拔赛3期-10题

蓝桥杯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. 下标 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题,需要的我私聊发你

总结

可能有更好的解法,欢迎大佬评论区喷我。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值