设为首页 加入收藏

TOP

HDU 4372 Count the Buildings(组合数学,第一类Stirling数)
2015-11-21 00:55:51 来源: 作者: 【 】 浏览:1
Tags:HDU 4372 Count the Buildings 组合 数学 一类 Stirling

HDU 4372

题意:有n个建筑高度为1~n,从前看能看到f个,从后看能看到b个,求可能有多少种排序情况。

思路:

五个小时花了3.5小时在上面,结果靠强行yy出了递推式(事后发现。。yy对了95%,跪在各种细节上,比赛结束也没A掉。。

只能说大力出奇迹!但这种奇迹往往会毁在不经意的细节上orz

?

?

分析几组数据我们可以发现,最高的n号楼一定是可以看到的,无论是从左还是右。

那么民那桑,先固定住n号楼的位置,将n号楼左边分为f-1组,右边b-1组,且用每组最高的那个元素代表这一组;

而后我们可以发现楼n的左边,从左到右,组与组之间最高的元素一定是单调递增的

且每组中的最高元素一定排在该组的最左边,每组中的其它元素可以任意排列(相当于这个组中所有元素的环排列,所谓环排列就是一个元素位置固定其他元素自己动,方案数等于(n-1)!)。

右边同理。

例如:n = 5 , b = 3 , f = 2。

显然n号楼所在位置一定在第3,或第4:XX5XX或XXX5X

当位置在3之时,左边2个元素分成2组,显然符合结论;

当位置在4之时,左边3个元素分成2组,左边可能的情况为:1 32 5X,21 3 5X ,2 31 5X , 1 42 5X ,21 4 5X ,2 41 5X ,1 43 5X ,31 4 5X ,3 41 5X...

均满足结论(当然这里的X很明显已经求出来了XP

?

故我们可以先把n-1个元素分成f-1+b-1组,每组做环排列,累计方案数即是答案。

?

n个人分成k组做环排列的方法数目,我们称之为第一类stirling数

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

?

code:

?

/*
* @author Novicer
* language : C++/C
*/
#include
  
   
#include
   
     #include
    
      #include
     
       #include
      
        #include
       
         #include
        
          #include
         
           #include
           #include
           
             #include
            
              #include
             
               #include
              
                #include
               
                 #include
                
                  #include
                 
                   #include
                  
                    #include
                   
                     #include
                    
                      #define INF 2147483647 #define cls(x) memset(x,0,sizeof(x)) #define rise(i,a,b) for(int i = a ; i <= b ; i++) using namespace std; const double eps(1e-8); typedef long long lint; const int maxn = 2000 + 5; const lint mod = 1e9 + 7; lint S[maxn][maxn]; lint C[maxn][maxn]; void init(){ for(int i = 0 ; i < maxn ; i++){ C[i][0]=1; C[i][i]=1; S[i][0]=0; S[i][i]=1; for(int j = 1 ; j < i ; j++){ C[i][j]=(C[i-1][j]%mod+C[i-1][j-1]%mod)%mod; S[i][j]=((i-1)%mod*S[i-1][j]%mod+S[i-1][j-1]%mod); } } } int main(){ // freopen(input.txt,r,stdin); int t ; cin >> t; init(); while(t--) { lint n,f,b; scanf(%I64d%I64d%I64d,&n,&f,&b); lint ans; if(b+f-2 <= 2000) ans=C[f+b-2][f-1]%mod*S[n-1][f+b-2]%mod; else ans = 0 % mod; printf(%I64d ,ans); } return 0; } 
                    
                   
                  
                 
                
               
              
             
            
           
         
        
       
      
     
    
   
  


?

?
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇设计模式之策略模式的C++实现 下一篇Codeforces Round #Pi (Div. 2) D..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: