算法回憶錄:母函數解決整數拆分

省略了不少內容,因此須要必定基礎纔可閱讀。主要爲了說清母函數如何解決此問題。
整數拆分:
一、整數拆分能夠理解爲蘋果放盤子問題(把N個蘋果放在M個盤子裏有多少種方法),只是這是至關於把N個蘋果放在N個盤子裏而已。
代碼:函數

int zh(int n,int m)
    {
        if(n==1 || m==1)
            return 1;
        if(n <= m)
            return (1 + zh(n, n-1));
            
        return zh(n, m-1) + zh(n-m, m);    
    }

二、整數拆分一樣能夠用遞推解決,其實這一樣用到了遞歸所得的關鍵函數關係: f(n, m) = f(n, m-1) + f(n-m, m)。code

for(int i=1; i<=n; i++) {
        for(int j=1; j<=n;j ++){
            if(i <= j){
                ans[j] += ans[j-i];
            }
        }
    }

三、用母函數解決: 這纔是本文的關鍵。
a、首先要理解爲何整數拆分能夠用G(x)=(1+x+x^2+x^3+x^4+……)(1+x^2+x^4+x^6)(1+x^3+x^6+x^9+……)(1+x^4+x^8+x^12+……)……表示。這個能夠這樣理解:第一項能夠理解爲用1來拆分,假使要求x^7的係數,那麼第一個多項式中的x^7就是由7個x相乘得出的(7=1+1+1+1+1+1+1),除此以外第一個多項x^2能夠與後面的多項式中的x^5相乘得出,這個能夠理解爲7=1+1+5。可是第2項的表達式中x^2*後項中x^5就是7=2+5。這個邏輯必須理解,這是G(x)解決整數拆分的關鍵思想。
b、如何理解代碼? 循環的控制很難理解:可是大致能夠這樣解釋:顯然c1存儲變量,c2爲臨時變量;執行一次i循環,c2則表示乘到當前多項式x的n次冪的係數爲c2[n],而後c2賦值到c1,c2初始化,繼續執行。遞歸

while (cin>>n) {
        for (i=0; i<=n; i++) { c1[i]=0;    c2[i]=0; }
        for (i=0; i<=n; i++) c1[i]=1;
        
        for (i=2; i<=n; i++) {
            //key code
            for (j=0; j<=n; j++) {
                for (k=0; k+j<=n; k+=i) {  
                    c2[j+k] += c1[j];  
                }
            }
                
            for (j=0; j<=n; j++) { 
                c1[j] = c2[j];    c2[j] = 0;  
            }
        }
        cout<< c1[n] <<endl;
    }
相關文章
相關標籤/搜索