1. 程式人生 > >演算法回憶錄:母函式解決整數拆分

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

省略了很多內容,所以需要一定基礎才可閱讀。主要為了說清母函式如何解決此問題。
整數拆分:
1、整數拆分可以理解為蘋果放盤子問題(把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); 
    }

2、整數拆分同樣可以用遞推解決,其實這同樣用到了遞迴所得的關鍵函式關係: f(n, m) = f(n, m-1) + f(n-m, m)。

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

3、用母函式解決: 這才是本文的關鍵。
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;
    }