求組合數Cnm的的方法


求一個組合數Cnm的值,Cnm= n! /(n-m)!*m!化簡的結果為

Cnm = (n*(n-1)*…*(n-m+1))/m!

這個直接求根據公式直接求顯然是不行的,當n和m較大時,顯然是要溢出的。目前知道兩種解決這種題的思路:

 

思路一:可以利用遞推關系式Cnm = C(n)(m-1) + C(n-1)(m-1)來實現,這樣初始化前幾個組合數,在根據題目要求處理的最大n和m值,遞推求出所有的Cnm,並保存。

實現方法以后補上。

 

思路二:為了避免直接計算n的階乘,可以直接對公式兩邊取對數,於是得到:ln(C(n,m)) = ln(n!) - ln(m!) - ln( (n-m)! )

對數有性質:ln(x*y) = ln(x) + ln(y),因此轉化成:

Ln(n!) = ln(1) + ln(2) + …+ln(n);

同理消去重疊的部分得到:

Cnm = (n*(n-1)*…*(n-m+1))/m!

 

因此這個算法時間復雜度仍然是 O( m ),雖然浮點計算比整數計算要慢,但解決了整數計算的溢出問題。

 

代碼實現(轉)

double cnm_lg(int n,int m)

{

  int i;

  double s1=0.0,s2=0.0;

  for(i=1;i<=m;i++)

    s1 += log(i);

  for(i=n-m+1;i<=n;i++)

    s2 += log(i);

  return s2-s1;

}

 

double cnm_double(int n,int m)

{

  if(m > n/2)

  m = n-m;

  return exp(cnm_lg(n,m));

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM