安利另外一篇(blog)
密码泥萌都知道
题面
题解
为了描述方便,这里将建筑称作(zsy)
高度为(n)的(zsy)无论如何都能从左右两侧看到。剩下的部分,从左边看到的是前缀(max),从右侧看到的是后缀(max)。大概像这样:
对于被框住的(A+B−1)个部分,只有第一个能作为前、后缀(max)被看到。可以认为是把数分成(A+B−1)个圆排列,其中有一个仅包含(n)。剩下的(A+B−2)个,先决定放在(n)的左边还是右边。然后,将每个圆排列的将最大值钦定为所在方向(左或右)上的第一个,并以此为关键字将圆排列排序后放置。
所以对于一组询问,答案就是:
[egin{bmatrix}n-1\A+B-2end{bmatrix} imesinom{A+B-2}{A-1}
]
代码
#include<bits/stdc++.h>
#define RG register
#define clear(x, y) memset(x, y, sizeof(x));
using namespace std;
inline int read()
{
int data=0, w=1;
char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') w=-1, ch=getchar();
while(ch>='0'&&ch<='9') data=data*10+(ch^48), ch=getchar();
return data*w;
}
const int mod(1e9 + 7), maxn(50010), maxk(210), K(201);
int T, n, A, B, C[maxk][maxk], S[maxn][maxk];
inline void Init()
{
C[0][0] = 1;
for(RG int i = 1; i <= K; i++)
{
C[i][0] = C[i][i] = 1;
for(RG int j = 1; j < i; j++) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;
}
for(RG int i = 0; i <= K; i++) S[i][i] = 1;
for(RG int i = 2; i <= maxn - 10; i++)
for(RG int j = 1; j < i && j <= K; j++)
S[i][j] = (1ll * (i - 1) * S[i - 1][j] % mod + S[i - 1][j - 1]) % mod;
}
int main()
{
T = read(); Init();
while(T--)
{
n = read(); A = read(); B = read();
if(A + B > n + 1) { puts("0"); continue; }
printf("%lld
", 1ll * C[A + B - 2][A - 1] * S[n - 1][A + B - 2] % mod);
}
return 0;
}