什麼是組合數呢?
從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 ...