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<=ed−1)
ed=n或者A[ed]>A[ed+1]ed=n 或者 A[ed] > A[ed+1]ed=n或者A[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 i分jjj段符合的排序的个数
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]=(i−j+1)∗f[i−1][j−1]+j∗f[i−1][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;
}
本文探讨了如何计算特定长度的排列中,含有指定数量上升段的序列个数。通过动态规划方法,定义状态转移方程,实现了高效计算。
428

被折叠的 条评论
为什么被折叠?



