分析:
一道很不套路的题,暴力DP就不说了(反正也过不了)。
以下内容转自洛谷用户星沐的题解:
思路:
把最高的楼k当做分水岭,剩下的部分,从左边看到的是前缀max,从右侧看到的是后缀max。(感谢叶学长),左边除去最高楼k有A—1个,右边除去最高楼k有B—1个,然后分成A+B-2的圆排列,A+B-2每栋楼可放左边也可放右边,再组合一下
(引用叶学长的话说,剩下的A+B-2个,先决定放在n的左边还是右边。然后,将每个圆排列的将最大值钦定为所在方向(左或右)上的第一个,并以此为关键字将圆排列排序后放置。)
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
typedef long long LL;
inline int read(){
int x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x;
}
const LL MOD=1e9+7;
int n,A,B;
LL c[205][205],str1[50005][205];
inline void pre_process(){
c[0][0]=1;
for(int i=1;i<=200;i++)
for(int j=0;j<=i;j++){
c[i][j]=c[i-1][j];
if(j) c[i][j]=(c[i][j]+c[i-1][j-1])%MOD;
}
str1[0][0]=1;
for(int i=1;i<=50000;i++)
for(int j=1;j<=200;j++)
str1[i][j]=(str1[i-1][j-1]+str1[i-1][j]*(i-1))%MOD;
}
int main(){
int T=read();
pre_process();
while(T--){
n=read(),A=read(),B=read();
printf("%lld\n",str1[n-1][A+B-2]*c[A+B-2][A-1]%MOD);
}
return 0;
}