[HDU4372] Count the Buildings
前言
第一类斯特林数,有思维难度
题目
讲解
考虑最高的那栋房子会被两边计算,除去它,还剩\(n-1\)栋房子
左边能看见的有\(F-1\)栋房子,右边能看见\(B-1\)栋房子
我们先考虑左边一边
如果我们选出了能被看见的\(F-1\)栋房子,剩下的所有高度小于它们的房子都会在它们的右边
对于每一栋选出的房子都会形成一条长龙,后面跟的就是高度小于它的房子,但不一定高度小于它的房子刚好跟在它后面
把这个看作一组,发现这一组便是第一类斯特林数中的一个环(重难点)
我们总共需要\(F-1+B-1\)个这样的环,方案数即为\(s[n-1][F+B-2]\),这里的\(s\)数组是第一类斯特林数
然后我们要在\(F+B-2\)个环中选出\(F-1\)个放在左边,顺序为根据排头高度递增
所以答案还要乘上\(C_{F+B-2}^{F-1}\)
最终的答案即为\(s[n-1][F+B-2]*C_{F+B-2}^{F-1}\)
记得判无解
代码
int C[MAXN][MAXN],s[MAXN][MAXN];
void pre(int x)
{
s[0][0] = C[0][0] = 1;
for(int i = 1;i <= x;++ i)
{
C[i][0] = 1;
for(int j = 1;j <= i;++ j)
C[i][j] = (C[i-1][j-1] + C[i-1][j]) % MOD,s[i][j] = (s[i-1][j-1] + 1ll * (i-1) * s[i-1][j]) % MOD;
}
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
pre(2000);
for(int T = Read(); T ;-- T)
{
n = Read();F = Read();B = Read();
if(F+B-2 > n-1) {Put(0,'\n');continue;}
Put(1ll * s[n-1][F+B-2] * C[F+B-2][F-1] % MOD,'\n');
}
return 0;
}