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

K 上 升 段 K上升段 K


题目

对于自然数1…n的一个排列A[1…N] 可以划分为若干个单调递增序列。每个单调递增序列由连续元素A[st…ed]组成,且满足以下条件:
1 < = s t , e d < = n ; 1<=st,ed<=n; 1<=st,ed<=n;
A [ i ] < A [ i + 1 ] ( s t < = i < = e d − 1 ) A[i]A[i]<A[i+1](st<=i<=ed1)
e d = n 或 者 A [ e d ] > A [ e d + 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)


解题思路

这题我们用 D P DP DP来做
f [ i , j ] f[i,j] f[i,j]为从 1   i 1~i 1 i j j j段符合的排序的个数
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,jF[i][j]=(ij+1)f[i1][j1]+jf[i1][j];(i<=n,j<n)

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

程序如下

#include
#include
#include 
#include

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;
}

你可能感兴趣的:(DP,ssl)