1. 程式人生 > >【知識】組合數學

【知識】組合數學

    組合數學,像數論一樣是發源自數學的噁心東西,在計算機上更是與取餘成為結髮夫妻,與DP和數論的關係也不一般。更因為計算機令人驚駭的列舉耐心,出現了更加可怕的變種題目。好了,現在進入正題。

    1.計數原理(我不願多說了)

    1)加法原理 2)乘法原理 3)抽屜原理 4)容斥原理

    尷尬事實:

    加法原理和乘法原理——基本不會單考...

    抽屜最多是你在草稿紙裡的證明步驟...

    容斥可以單獨考但大多還是會和素數、DP或組合數一起考,讓人噁心...

    2.組合數(總是要打表...)

    1)階乘法:

    根據組合數公式:C(n,m)=n!/m!/(n-m)!

,在需要組合數不多(例如只求一個)且精度在整形、長整形或無符號長整形中可以存下這個階乘便可以使用,可以先將大於n/2的m轉換一下就可以較快求出了。有時除法又可以結合逆元(只不過不太好用就是了,老是不互質就很尷尬了)(O(n):1+空間1)

    2)楊輝三角法:

    根據組合數公式:C(n,m)=C(n-1,m)+C(n-1,m-1),可以很輕鬆地求出一大批組合數,只要n、m不會太大就可以很方便地求出來,一次性求出很多組合數,但有些佔用記憶體,而且如果組合數用的不多會很虧。不過還是最常用的方法,因為楊輝三角只涉及到加法,取餘很容易,不需很麻煩。(O(n^2):n^2+空間n^2)

    3)Lucas定理法:

    根據組合數公式:C(n,m)%p(p為質數)=C(n/p,m/p)*C(n%p,m%p)%p ,可以快速求出組合數取餘並不用擔心溢位,但只適用於p很小並且n、m大於p時,例如n、m上限為1e9,p上限為1e5之類。但通常需要配合階乘法或楊輝三角法求出小一些的組合數,較為複雜。預處理:O(p^2)+求值:O(log(n,p)):1+空間:p^2

    4)特殊情況:

    有時候組合數和數論一起考的話,可以用分解質因數後質因子的次數來表示這一個組合數,用來判斷倍數很有效

    3.組合數學DP

    如果你還不知道這是什麼,請點選湫秋系列故事——安排座位,然後就會理解這種題的噁心之處了。組合數學DP像這種需要很牛的思維,計算方案一定要不重不漏,例如這道題所有方案都要考慮,不能以為只有插在正常序列才是合法的,有可能剛好插在不合法孔中反而讓它變成了合法序列都是要考慮的。還有

A Famous Stone Collector也是如此。但也不多說了,還是看看下面的經典組合問題吧!

    4.盒子與小球

    接受盒盒球球的制裁吧!

    1)給你k個小球放入n個盒子,小球全都相同,盒子全都不同,盒子可為空,求方案總數,難度係數★★☆

    考慮如下方程,解的個數即為答案

    X1+X2+X3+...+Xn=k(Xi∈N)

    將所有X加上1變成Y,答案不變

    Y1+Y2+Y3+...+Yn=k+n(Yi∈N*)

    由於考慮順序,所以就類似於某個經典問題——小球擋板,用擋板法可得解為

   C(k+n-1,n-1)

    2)給你k個小球放入n個盒子,小球全都不同,盒子全都相同,盒子可為空,求方案總數,難度係數★★★

    裸的斯特林數還用說什麼(當然要說不那麼裸就將盒子裡先墊上幾個虛假的球使盒子不能為空)

   S(k+n,n)

    3)給你k個小球放入n個盒子,小球全都不同,盒子全都不同,盒子可為空,求方案總數,難度係數★★★★

    其實在第2問後就顯得很簡單了,只需要把盒子隨機亂排即可

    S(k+n,n)*n!

    4)給你k個小球放入n個盒子,小球全都相同,盒子全都相同,盒子可為空,求方案總數,難度係數★★★★★

    整數的分解型題,DP解

    P(i,j)表示i個球放入j個盒子方案數

    P(i,j)=sum(P(i-j,k))(1<=k<=j)

    P(1,1)=1

    然後一樣的將盒子全都墊上一個球

    解為

    P(k+n,n)

    5.注意事項

    1)精度

    通常關於組合數學的題都會出現極大的答案,所以通常會模一個數,而在模之前(非常)有可能會出現乘法溢位,所以要實現估計好使用的精度,是用int(其實基本上都會爆)、long long(還好,但也必須步步模)還是unsigned long long(其實也很少用)必須要準

    2)記憶體

    像是楊輝三角之類的表什麼的很容易爆掉記憶體,必須在使用時儘量不觸犯記憶體上限,例如可以C(n,n/2-k)就不要C(n,n/2+k)什麼的

    3)除法

    要知道取餘最忌諱除法了,不然就只能用逆元很讓人傷腦筋。不是因為逆元難求,而是因為求逆元有可能根本就沒有逆元,即便是對素數的逆元,也不見得就有(可能這個數本身是被取餘數的倍數)。要謹慎使用逆元