組合數演算法

2021-08-07 06:05:56 字數 2566 閱讀 9616

什麼是組合數呢?

從m個不同元素中取出n(n≤m)個元素的所有組合的個數,叫做從m個不同元素中取出n個元素的組合數(combination)。

組合數基本公式為: cn

m=m!

n!(m

−n)!

線性寫法為:c(m,n) = m!/((m-n)!*n!)

現實生活中彩票的概率計算就涉及到組合數,比如雙色球中紅球選擇需要從01~33紅球中選出6個,組合結果為 c(33,6) = 1107568.

由於計算機資料儲存方式的限制,階乘的計算,如果是long int型只能正確計算到12左右的階乘,如果用double型只能正確計算170左右的階乘,當然這些只是大概,需要結合實際平台進行驗證。

所以採用階乘計算稍大數組合數是不合適的,而且效率不高,但是可以先對公式進行轉換然後再進行計算:

1.對公式兩邊取自然對數ln

(cnm

)=ln

(m!n

!(m−

n)!)

2.根據對數性質進行轉換ln

(cnm

)=ln

(m!)

−ln(

n!)−

ln((

m−n)

!) l

n(cn

m)=∑

i=1m

ln(i

)−∑i

=1nl

n(i)

−∑i=

1m−n

ln(i

) 3.進行計算

以第2步得到的公式計算出 ln

(cnm

) 的值,然後再取反對數就可以得到組合數結果了。

用這種方法計算組合數,如果只計算ln(c(m,n))的話,n可以取到整型資料的極限值65535,

ln(c(65535,32767)) = 45419.6
而計算時間可以達到毫秒級。當然,如果要取反對數得到最終的組合數的話,m的取值就不能達到這麼大了,但是這種演算法仍然可以保證m取到1000以上。

4.該演算法oc實現**

/**

組合數計算

@param totalnum c(m,n) 中 m

@param requirenum c(m,n) 中 n

@return 組合數結果

*/+ (nsinteger)selectfromtotalnum:(nsinteger)totalnum requirenum:(nsinteger)requirenum

if (requirenum < totalnum / 2.0)

double s1 = 0;

for (nsinteger i = requirenum + 1; i <= totalnum; i ++)

double s2 = 0;

nsinteger ub = totalnum - requirenum;

for (int i = 1; i <= ub; i++)

double result = exp(s1 - s2);

//此處需要先進行四捨五入,不能直接強行取整,不然可能會有 1 的誤差值

double temp = round(result); //四捨五入

return (nsinteger)temp;

}

所有的可能性組合可以通過排列組合獲得,該方式計算耗時長、資源占用嚴重,在iphone6上測試僅 c(33,16) 的計算就需 12s左右的時間,記憶體和cpu更是爆滿,但是當 m <= 10 時 還是可以接受的,所以該方法具有很大的侷限性。

+ (nsarray *)selectfromsource:(nsarray *)source requirenum:(int)requirenumelse

}//第一種排列組合結果就是選擇前 choosenum 個元素

[results addobject:firstitem];

while (1)

if ((index

< source.count - 1) && [arr[index] isequal:@1] && [arr[index + 1] isequal:@0])

];//替換arr中 index 左側元素

[arr replaceobjectsinrange:nsmakerange(0, index) withobjectsfromarray:temparr];

//將已選擇的元素挑選出來儲存

nsmutablearray *selectedarr = [nsmutablearray array];

for (int j = 0; j < arr.count; j ++)

}[results addobject:[selectedarr mutablecopy]];

break;}}

}}

DP演算法求組合數

dp演算法求組合數 中學就學過排列,組合 比如 c5,2 10 c6,2 15 如果用演算法實現的話,難道也要先做一連串的乘法,然後再相除嗎?比如 c5,2 5 4 3 2 3 2 如果數很大的話,又是乘又做除的,多牛的計算機才能搞定呢?先看看簡單的 2個數選2個,共有1種方法 3個數選2個,共有3...

ACM演算法 組合數學

卡特蘭數 問題 n對括號有多少種合法的匹配方式?卡特蘭數的常見應用之一 結論 對於n對括號,合法的排列共有c n,2n c n 1,2n 基本思路 考慮n對括號,有n個 和n個 對於任意乙個 其前面必定有乙個 跟他對應,如果沒有則是非法序列。也就是說,對於 其前面的 的數量必須大於等於 的數量。假設...

組合數學 求組合數

對於求組合數,要根據所給資料範圍來選擇合適的演算法 這道題中所給的資料範圍適合用打表的方法直接暴力求解 先用4e6的複雜度預處理出所有的情況,再用1e4的複雜度完成詢問即可 include using namespace std const int n 2010 const int mod 1e9 ...