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;
}

浙公网安备 33010602011771号