定義:從 n 個不同元素的集合中,任意取出 m(m<=n) 個元素排成一列(有先後順序)稱為乙個排列;此種排列的總數即為排列數,即叫做從 n 個不同元素中取出 m 和元素的排列數。
公式:
(當 n=m 時,分母為 0! = 1,即為全排列)
推導:在具有 n 個數的集合中,順序取出 m 個數,成為乙個排列。
上述過程符合「分步乘法計數」場景,應用分步乘法計數公式:
得到 n(n-1)(n-2)…(n-m+1),即 a(n, m) = n! / (n-m)! 。
定義:從 n 個不同元素的集合中,任意取出 m(m<=n) 個元素並成一組(無先後順序),叫做從 n 個不同元素中取出 m 個元素的乙個組合;從 n 個不同元素的集合中取出 m(m<=n) 個元素的所有組合的個數,叫做從 n 個不同元素中取出 m 個元素的組合數。
公式:
推導:在具有 n 個數的集合中,獲取 m 個數組成一組。
首先依舊可以得到排列數 a(n, m),但又因為組合數是無序的,而排列數是有序的,所以需要在 a(n, m) 的基礎上去除掉元素組合一致的排列。即 c(n, m) = a(n, m) / m! 。這裡的理解需要轉一下彎,所以我們通過下述證明來輔助理解這條公式。
證明:a(n, m) = c(n, m) * a(m, m)
第一步,從 n 個球中取出 m 個來,先不排序,所以為組合數問題,得到 c(n, m)。
第二步,將第一步取出的球全部排列,a(m, m) = m!,即求組合的全排列。
第三步,應用分步乘法計數原理,得到 a(n, m) = c(n, m) * a(m, m),即 a(n, m) = c(n, m) * m! 得證。
所以從 n 中取出 m 的排列數,實際為從 n 中取出 m 的組合數與每乙個組合自身所擁有的全排列數的乘積。
定義:重複組合是一種特殊的組合,從 n 個不同元素的集合中允許重複地取出 m 個元素(任意取出乙個元素,然後再將其放回到集合中)形成乙個組合,叫做從 n 個元素中取出 m 個元素的重複組合。
公式:
分析(放球模型):將重複組合的概念轉換為放球模型來進行分析,將 n 個不同的元素當作 n 個不同的格仔,既有 n-1 塊相同的隔板。同時用 m 個相同的小球,當作取出 m 個元素。現在問將 m 個相同的小球放到 n 個格仔裡,有多少種方法?
相當於:
最後再給出組合數恒等公式,大家不妨自己推導一下吧。
排列與組合
include using namespace std void perm int a,int n,int m,int out,int k,int used cout endl for int i 0 i n i void combine int a,int n,int m,int out,int ...
排列與組合
試想這樣乙個問題 一組數比如 任取其中的三邊,會構成多少種不同的三角型 又或者任取其中四邊,會構成多少種不同的多邊形?如果取三邊,或五邊又如何?在一些情況下,我們需要解決處理排列和組合數的問題 先來看一下排列的情況 abcd 下標 1234 解決乙個陣列平移的問題並不難 abcd 向左移動4次,就可...
排列與組合 回溯
求1.n的全排序或者m組合實際上是乙個回溯問題,對於回溯問題,如何寫出遞迴程式,關鍵在於想好問題隱式解空間樹,之後,可以按照標準的dfs去遍歷解空間樹,並在適當的時候剪枝,對於全排列,不需要也不能進行減枝,每個葉子節點都對應乙個全排列。對於組合問題,實際上只要限定,產生m個數的下標是從小到大排列的就...