题意:有 个节点,按顺序入栈出栈,中间当第 个数入栈之后,要求栈内有 个元素,问一共这 个节点全部入栈完,再全部出栈,有多少种入栈出栈的顺序。
思路:我们可以设入栈为 ,出栈为 ,则满足题意的 串,前 长度的 串中, 比 要少 个,且每个前缀串的 的数量要不少于 的数量,由此转换成求卡特兰数。
卡特兰数:
满足递推式:
通项为:
拓展到一般情况:
比如一个
串,要求有
个
,
个
,且每个前缀子串的
的个数要不小于
的个数,则这样的串的数量即为卡特兰数。
(此情况为串中0代表元素相同,1代表元素相同)
(此情况为串中0代表元素各不相同,1代表元素各不相同)
#include<iostream>
#include<climits>
using namespace std;
#define mod 1000000007
int inv[2000005];
int mul[2000005];
int fac[2000005];
int c(int n, int m)
{
m = min(m, n - m);
if (m < 0)
return 0;
return (((((1LL * mul[n]) % mod) * fac[m]) % mod) * fac[n - m]) % mod;
}
int solve(int m, int n)
{
return (c(m + n, n) - c(m + n, n - 1) + mod) % mod;
}
int main()
{
int T;
int n, m, k;
mul[0] = inv[0] = mul[1] = inv[1] = fac[0] = fac[1] = 1;
for (int i = 2; i <= 2000000; ++i)
{
mul[i] = 1LL * mul[i - 1] * i % mod;
inv[i] = 1LL * (mod - mod / i) * inv[mod % i] % mod;
fac[i] = 1LL * fac[i - 1] * inv[i] % mod;
}
cin >> T;
while(T--)
{
cin >> n >> m >> k;
cout << 1LL * solve(m - 1, m - k) * solve(n - m + k, n - m) % mod << '\n';
}
return 0;
}