标签:ini span string 方法 out math space color mat
解题关键:
n的环排列的个数与n-1个元素的排列的个数相等。
首先可以肯定,无论从最左边还是从最右边看,最高的那个楼一定是可以看到的,从这里入手。
假设最高的楼的位置固定,最高楼的编号为n,那么我们为了满足条件,可以在楼n的左边分x-1组,右边分y-1组,且用每组最高的那个元素代表这一组,那么楼n的左边,从左到右,组与组之间最高的元素一定是单调递增的,且每组中的最高元素一定排在该组的最左边,每组中的其它元素可以任意排列(相当于这个组中所有元素的环排列)。右边反之亦然。
最高的那个楼左边一定有x-1个组,右边一定有y-1个组,且每组是一个环排列,这就引出了第一类Stirling数(个人分成组,每组内再按特定顺序围圈的分组方法的数目)。我们可以先把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<<"\n"; 34 } 35 return 0; 36 }
标签:ini span string 方法 out math space color mat
原文地址:http://www.cnblogs.com/elpsycongroo/p/7349605.html