1. 程式人生 > >演算法學習之組合數學入門基礎

演算法學習之組合數學入門基礎

組合數學基礎知識,整理所學。

    一.  組合數遞推公式:
        ��_��^��=��_(��−1)^(��−1)+��_(��−1)^��  
        C(n,m) = C(n-1,m)+C(n-1,m-1);

    二.   鴿籠原理
        描述:如果n個物體被放進m個盒子,那麼至少有一個盒子有⌈��/��⌉個物體。 -->意思為向上取整,用floor函式可以實現
        經典案例: 
            對數列a1,a2,a3,……an,至少存在1≤i<j≤n,使得∑1_(��=��)^�� ��_�� 能被n整除。 -->即ai+..+aj 能被n整除。
        證明如下:
            作和函式 S1 = a1;S2 = a1+a2... ;Sn = a1+a2+a3+..+an; 假設這n個數不能被n整除,則餘數的域為1--n-1,
            這就相當於把n-1個數放進n個籠子,肯定有兩個餘數相等,則肯定有Sj - Si 能被n整除。

       三.   容斥原理
        幾個集合並集的大小=所有單個集合的大小之和-(所有任意)兩個的交+(所有任意)三個的交-(所有任意)四個的交……
        比如��∪��∪�� = ��+��+��−��∩��−��∩��−��∩��+��∩��∩��



    四. 母函式 --生成函式 
        在數學中,某個序列的母函式(Generating function,又稱生成函式)是一種形式冪級數
        其每一項的係數可以提供關於這個序列的資訊。使用母函式解決問題的方法稱為母函式方法。


      普通型母函式

        舉個例子:
            若有1克、2克、3克、4克的砝碼各一枚,能稱出哪幾種重量?各有幾種可能方案?

            現在x的指數表示稱出的重量。
            1個1克的砝碼可以用函式1+1*x^1表示,  
            1個2克的砝碼可以用函式1+1*x^2表示, //如果有3個2g的砝碼呢? 表示為 1+x^2+x^4+x^6
            1個3克的砝碼可以用函式1+1*x^3表示,
            1個4克的砝碼可以用函式1+1*x^4表示,

      我們拿1+x^2來說,前面已經說過,x表示砝碼,x的指數表示砝碼的重量!初始狀態時,這裡就是一個質量為2的砝碼。
        那麼前面的1表示什麼?按照上面的理解,1其實應該寫為:1*x^0,即1代表重量為2的砝碼數量為0個。
        所以這裡1+1*x^2 = 1*x^0 + 1*x^2,即表示2克的砝碼有兩種狀態,不取或取,不取則為1*x^0,取則為1*x^2
        接下來我們把他們乘起來(1+��)*(1+��^2)*(1+��^3)*(1+��^4=1+��+��^2+〖2��〗^3+2��^4+2��^5+2��^6+2��^7+��^8+��^9+��^10
            指數即拿的重量,係數就是對應的方案數(zhen tm niu bai)

    五.  母函式模板: 
        存多項式。使用陣列維護的。下標是多項式的指數,存的是該項的係數!
        存多項式。使用陣列維護的。下標是多項式的指數,存的是該項的係數!

//注意所有操作是從下標為0開始的! a[0]就是 1的係數,也就是常數項
#include
using namespace std;
int a[1000],b[1000];//a存多項式,下標是指數,存的是係數! b是中間的,存每一次的結果!
int v[100],num[100]; //硬幣面值,個數
int n; //n是硬幣種類數
void GFunction(){
for(int i= 0;i<=num[0]*v[0];i++) a[i] = 1; //初始化,
int lastindex = num[0]*v[0]; //記錄目前最大的多項式指數
for(int i = 1;i