【HDU4372】Count the Buildings (第一类斯特林数)

Description

$N$座高楼,高度均不同且为$1~N$中的数,从前向后看能看到$F$个,从后向前看能看到$B$个,问有多少种可能的排列数。

$T$组询问,答案模$1000000007$。其中$n\leq 2000,T\leq 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\n",s[N-1][F+B-2]*c[F+B-2][F-1]%mod);
28     }
29 }

猜你喜欢

转载自www.cnblogs.com/ezoiLZH/p/9425402.html