NKOJ 排列 [递推]
问题描述
将自然数 1 到 n 任意排列,然后在排列的每两个数之间根据他们的大小关系插入“>”和“<”。 例如:对于 1..5 的一个排列:3 2 4 1 5,可得到:3 > 2 < 4 > 1 < 5,其中有两个“>”和 2 个“<” 。 现在给出自然数 n,问在自然数 1..n 的所有排列中,有多少个排列恰好有 k 个“<”。 请你解答这个问题。
输入格式
包含多组数据。第一行一个整数 T,表示有 T 组数据。
每组数据的占一行,包含两个整数 n 和 k,它们之间用一个空格分开。
输出格式
共 T 行,每组数据输出一行,每行一个整数,表示对应输入的排列数,这个数如果很大,则需要 输出 mod 1000000007 的结果。
解法
表示从1到 有 个 的方案数
在每一个 后面 或 开头插入 :
在每一个 后面 或 末尾插入 (多一个 ):
得到方程:
代码
#include<iostream>
#include<cstdio>
#define M 1000000007
#define ll long long
using namespace std;
ll f[1010][1010];
int main(){
ll t;scanf("%lld",&t);
for(ll i=0;i<=1000;i++)f[i][0]=1;
for(ll i=1;i<=1000;i++)
for(ll j=1;j<=1000;j++)
f[i][j]=(f[i-1][j-1]*(i-j)+f[i-1][j]*(j+1))%M;
for(ll i=1;i<=t;i++){
ll n,k;scanf("%lld%lld",&n,&k);
printf("%lld\n",f[n][k]);
}
return 0;
}