给定n栋楼 拍成一列,从前边往后看能看到b栋楼,从后往前能看到f栋楼,问有多少种组合方式.
那么最高的那栋楼,肯定是前与后的分界点,
先考虑从前往后看,假设看到了x栋楼, 那么最高楼前面 肯定有x-1 组,每组最高的肯定是在最前面,这样 就只能看到x栋楼。
同样后面看到y栋,则最高的后面有y-1组,这样一共就是x-1+y-1组,每组其实又是一个环排列,那么题目可转化为 n-1栋楼求 (x-1+y-1)个环排列
也就是求斯特林数,每次要从这些组中选x-1组放在前面,所以还有乘一个组合数C[x-1+y-1][x-1];
ans = Stirling[n-1][x-1+y-1] *C[x-1+y-1][x-1];
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstring>
#include <climits>
using namespace std;
int gcd(int a,int b){ return b==0?a:gcd(b,a%b); }
typedef long long llt ;
#define MOD 1000000007
const int SIZE = 2005;
llt C[SIZE][SIZE] = {0};
//生成组合数
void initC(){
for(int i=0;i<SIZE;++i)for(int j=0;j<=i;++j){
if ( 0 == j || i == j ) C[i][j] = 1;
else C[i][j] = (C[i-1][j-1] + C[i-1][j]) % MOD;
}
C[0][0] = 1;//此处看情况
}
llt S[SIZE][SIZE];
void initStirling(){
memset( S,0,sizeof(S));//慎重memset
S[1][1] = 1;
for (int i = 1;i < SIZE;++i) for (int k = 1;k < SIZE;++k){
if (i == 1 && k == 1)continue;
S[i][k] = (S[i-1][k-1] + ((i-1) * S[i-1][k])% MOD ) % MOD;
}
}
int main(){
initC();
initStirling();
int kase;
scanf("%d",&kase);
while(kase--){
int n,f,b;
llt ans;
scanf("%d%d%d",&n,&f,&b);
//题目数据会给出不成立的情况,所以先判断一下,否则一直re。。。。
if ( f + b > n+1) ans = 0LL;
else
ans = S[n-1][f-1+b-1]*C[f-1+b-1][f-1];
printf("%I64d\n",ans%MOD);
}
}