Description
$N$座高楼,高度均不同且为$1~N$中的数,从前向后看能看到$F$个,从后向前看能看到$B$个,问有多少种可能的排列数。
$T$组询问,答案模$1000000007$。其中$nleq 2000,Tleq 100000$
题解:
可以考虑现将最高的拿出来,那么可以考虑左边需要有$F-1$个房子成递增关系,那么可以将左边的房子分成$F-1$个组,右边有$B-1$个房子成递减关系,也是如此。
不禁想到第一类斯特林数,$s(p,k)$是将将$p$个物体排成$k$个非空循环排列的方法数($k$个排列是有先后顺序的)。
可以想到,每一组都是有顺序的(与环等价,每组把最高的转到第一个,每组再按第一个排序,右边同理,普通排序不能保证只有F个递增,B个递减)。
除此之外,还要计算组合数,就是在$(F-1+B-1)$组中取出$F-1$个到左边,乘上即是答案。
CODE:
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 5 #define mod 1000000007 6 int T,N,F,B; 7 long long c[2005][2005]; 8 long long s[2005][2005]; 9 10 void init(){ 11 c[0][0]=s[0][0]=1; 12 for(int i=1;i<=2000;i++){ 13 s[i][0]=0; 14 c[i][0]=1; 15 for(int j=1;j<=i;j++){ 16 s[i][j]=((i-1)*s[i-1][j]+s[i-1][j-1])%mod; 17 c[i][j]=( c[i-1][j]+c[i-1][j-1])%mod; 18 } 19 } 20 } 21 22 int main(){ 23 init(); 24 scanf("%d",&T); 25 while(T--){ 26 scanf("%d%d%d",&N,&F,&B); 27 printf("%d ",s[N-1][F+B-2]*c[F+B-2][F-1]%mod); 28 } 29 }