【12年特长生模拟第二题】【DP】K上升段

本文探讨了如何计算特定长度的排列中,含有指定数量上升段的序列个数。通过动态规划方法,定义状态转移方程,实现了高效计算。

K上升段K上升段K


题目

对于自然数1…n的一个排列A[1…N] 可以划分为若干个单调递增序列。每个单调递增序列由连续元素A[st…ed]组成,且满足以下条件:
1<=st,ed<=n;1<=st,ed<=n;1<=st,ed<=n;
A[i]<A[i+1](st<=i<=ed−1)A[i]<A[i+1] (st<=i<=ed-1)A[i]<A[i+1](st<=i<=ed1)
ed=n或者A[ed]>A[ed+1]ed=n 或者 A[ed] > A[ed+1]ed=nA[ed]>A[ed+1]
例如:排列1 2 4 5 6 3 9 10 7 8 可划分为3个单调递增序列 1 2 3 4 5 6;3 9 10 ;7 8 ; 所以我们称这是一个 3上升段序列 。
现在给定n和k , 求出n的全排列中的,k上升段序列的个数。


输入

输入仅有1行,包含两个数n, k(1 < n < 20, 1 < k < n)。

输出

输出n的所有k上升段的个数。


输入样例

K.IN
3 2

输出样例

K.OUT
4

说明

( 说明,符合条件的排列是132,312,213,231)


解题思路

这题我们用DPDPDP来做
f[i,j]f[i,j]f[i,j]为从1 i1~i1 ijjj段符合的排序的个数
F[i][j]=(i−j+1)∗f[i−1][j−1]+j∗f[i−1][j];(i<=n,j<n)F[i][j]=(i-j+1)*f[i-1][j-1]+j*f[i-1][j];(i<=n,j<n)F[i][j]=(ij+1)f[i1][j1]+jf[i1][j];(i<=n,j<n)

其中i表示i的全排列,j表示划分的段数

程序如下

#include<cstdio>
#include<cstring>
#include<iostream> 
#include<algorithm>

using namespace std;

int n,k;

long long f[2001][2001];

int main()
{
	scanf("%d%d", &n, &k);
	for(int i = 1; i <= n; ++i)
	for(int j = 1; j <= k; ++j)
	if(i == j) f[i][j] = 1;
	else f[i][j] = j * f[i - 1][j] + (i - j + 1) * f[i - 1][j - 1];
	printf("%lld", f[n][k]);
	return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值