zoukankan      html  css  js  c++  java
  • [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 }
  • 相关阅读:
    闭包和this
    闭包与变量
    闭包
    ES6扩展运算符的几个小技巧
    js对象的深拷贝
    js获取当前点击元素的索引
    前端学习指北
    css实现心形图案
    this 知多少
    js数字进制转换
  • 原文地址:https://www.cnblogs.com/elpsycongroo/p/7349605.html
Copyright © 2011-2022 走看看