HDU4372(第一类斯特林数)

来源:互联网 发布:python手机自动化脚本 编辑:程序博客网 时间:2024/04/28 19:17

HDU4372(第一类斯特林数)

分类: 组合博弈 27人阅读 评论(0) 收藏 举报

题目:Count the Buildings


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

0 < N, F, B <= 2000


首先我们知道一个结论:n的环排列的个数与n-1个元素的排列的个数相等,因为P(n,n)/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的左边。所以答案是

ans(n, f, b) = C[f + b - 2][f - 1] * S[n - 1][f + b - 2];


[cpp] view plaincopy
  1. #include <iostream>  
  2. #include <string.h>  
  3. #include <stdio.h>  
  4.   
  5. using namespace std;  
  6. typedef long long LL;  
  7.   
  8. const int N=2005;  
  9. const LL MOD=1000000007;  
  10.   
  11. LL C[N][N];  
  12. LL S[N][N];  
  13.   
  14. void Init()  
  15. {  
  16.     int i,j;  
  17.     for(i=0;i<N;i++)  
  18.     {  
  19.         C[i][0]=1;  
  20.         C[i][i]=1;  
  21.         S[i][0]=0;  
  22.         S[i][i]=1;  
  23.         for(j=1;j<i;j++)  
  24.         {  
  25.             C[i][j]=(C[i-1][j]%MOD+C[i-1][j-1]%MOD)%MOD;  
  26.             S[i][j]=((i-1)%MOD*S[i-1][j]%MOD+S[i-1][j-1]%MOD);  
  27.         }  
  28.     }  
  29. }  
  30.   
  31. int main()  
  32. {  
  33.     LL t,n,f,b,ans;  
  34.     Init();  
  35.     scanf("%I64d",&t);  
  36.     while(t--)  
  37.     {  
  38.         scanf("%I64d%I64d%I64d",&n,&f,&b);  
  39.         ans=C[f+b-2][f-1]%MOD*S[n-1][f+b-2]%MOD;  
  40.         printf("%I64d\n",ans);  
  41.     }  
  42.     return 0;  
  43. }  
原创粉丝点击