P4609 [FJOI2016] 建筑师 题解 / 第一类斯特林数

题目传送门:P4609 [FJOI2016] 建筑师

首先高度为 \(n\) 的大楼一定都能看到,相当于将 \(n\) 分成了两部分,那么情况如下图所示。

相当于总共有 \(A+B-2\) 组,每一组最高的楼固定,其余可以随便排列的方案数,容易发现这就是个圆排列,令最高的楼为圆的起点,那么答案即为 \(n-1 \brack A+B-2\),因为 \(n\) 不在组内。

然后左右使用什么组都没有关系,直接 \(A+B-2 \choose A-1\)

最后答案即为 \({n-1 \brack A+B-2}{A+B-2 \choose A-1}\),预处理即可。

#include<bits/stdc++.h>
#define double long double
using namespace std;
const int N=50010,M=510,mod=1e9+7;
int c[N][M],s[N][M];
inline int read(){
	char c=getchar();
	int f=1,ans=0;
	while(c<48||c>57) f=(c==45?f=-1:1),c=getchar();
	while(c>=48&&c<=57) ans=(ans<<1)+(ans<<3)+(c^48),c=getchar();
	return ans*f;
}
main(){
	c[0][0]=s[0][0]=1;
	for (int i=1;i<N;i++){
		c[i][0]=1;
		for (int j=1;j<M;j++) c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod,s[i][j]=(1ll*(i-1)*s[i-1][j]%mod+s[i-1][j-1])%mod;
	}
	int T=read();
	while(T--){
		int n=read(),A=read(),B=read();
		printf("%d\n",1ll*s[n-1][A+B-2]*c[A+B-2][A-1]%mod);
	}
    return 0;
}
posted @ 2026-01-26 11:46  OTn53_qwq  阅读(7)  评论(0)    收藏  举报