[hdu4372]counting buildings

解题关键:

n的环排列的个数与n-1个元素的排列的个数相等。

首先可以肯定,无论从最左边还是从最右边看,最高的那个楼一定是可以看到的,从这里入手。

假设最高的楼的位置固定,最高楼的编号为n,那么我们为了满足条件,可以在楼n的左边分x-1组,右边分y-1组,且用每组最高的那个元素代表这一组,那么楼n的左边,从左到右,组与组之间最高的元素一定是单调递增的,且每组中的最高元素一定排在该组的最左边,每组中的其它元素可以任意排列(相当于这个组中所有元素的环排列)。右边反之亦然。

最高的那个楼左边一定有x-1个组,右边一定有y-1个组,且每组是一个环排列,这就引出了第一类Stirling数($n$个人分成$k$组,每组内再按特定顺序围圈的分组方法的数目)。我们可以先把n-1个元素分成x-1+y-1组,然后每组内部做环排列。再在所有组中选取x-1组放到楼n的左边。所以答案是Stirling[n-1][x-1+y-1]*C[x-1+y-1][x-1](组合数);

预处理$O(N^2)$。对于每组询问$O(1)$解决。

第一类stirling数是环之间是无顺序的

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<iostream>
 7 using namespace std;
 8 typedef long long ll;
 9 const int maxn=2002;
10 const int mod=1e9+7;
11 ll comb1[maxn][maxn],stir[maxn][maxn];//2w*2w会爆掉
12 void init1(){
13     comb1[0][0]=stir[0][0]=1;
14     for(int i=1;i<maxn;i++){
15         comb1[i][i]=comb1[i][0]=1;
16         stir[i][0]=0;stir[i][i]=1;
17         for(int j=1;j<i;j++){
18             comb1[i][j]=(comb1[i-1][j-1]+comb1[i-1][j])%mod;
19             stir[i][j]=((i-1)*stir[i-1][j]+stir[i-1][j-1])%mod;
20         }
21     }
22 }
23 
24 int main(){
25     int t,f,b,n;
26     init1();
27     cin>>t;
28     while(t--){
29         cin>>n>>f>>b;
30         ll ans=0;
31         if(f+b-2<=2000) ans=(1ll*stir[n-1][b+f-2]*comb1[b+f-2][b-1]+mod)%mod;
32         else ans=0;
33         cout<<ans<<"
";
34     }
35     return 0;
36 }
原文地址:https://www.cnblogs.com/elpsycongroo/p/7349605.html