Project Euler 78 : Coin partitions

Project Euler 78 : Coin partitions

Integer Partition

Let p(n) represent the number of different ways in which n coins can be separated into piles. For example, five coins can be separated into piles in exactly seven different ways, so p(5)=7.

| OOOOO |
| OOOO O |
| OOO OO |
| OOO O O |
| OO OO O |
| OO O O O |
| O O O O O |

Find the least value of n for which p(n) is divisible by one million.

既然題目都告訴了是coin partitions,那麼直接按照分硬幣的思路做肯定沒問題,至於硬幣如何分,參見硬幣劃分

題目的意思就是任意麪值的硬幣咯,也就是用1~n的硬幣來劃分n。哈哈直接套用以前的結論,驗證題目中的p(5)=7 ,5塊錢用1,2,3,4,5來分,那麼應該是1(1x)(1x2)(1x3)(1x4)(1x5)x5 的係數,唔,展開即可。

什麼你問我怎麼展開?額,根據11x=1+x+x2+x3+....... 然後乘起來慢慢算。。不過我們有Mathematica大殺器,可以來方便的求係數,如下:

這裏寫圖片描述

於是襯衫的價格是9磅15便士,應該選擇B項。(答案應該是7)

看來沒錯,等等,似乎發現了什麼驚天的祕密。

似乎,我們得到了p(n) 的生成函數 n=0P(n)xn=n=111xn

於是興沖沖的來做這題,於是瞬間懵逼,完全沒法啃,每次計算都不知道要花多久,跟別談求這樣一個連區間都沒有的題了。

Bing了一下,這個p(n) 果然來頭不小,上面的那個生成函數早就被歐拉發現了,又見歐拉!於是繼續搜,找到了這個,Computing the Partitions of n,簡單樸實的網頁裏給出了這樣的一個公式。

P(n)=(1)k1(P(n12k(3k+1))+P(n12k(3k1)))

其中k從1開始,直到迭代到無法迭代,即n<0。經過觀察,12k(3k+1) 是一個等差數列和的形式,其通項爲2+3k ,同理後面的那一個通項爲1+3k

既然是迭代公式,那麼直接開好數組,一路迭代上去即可,於是代碼如下:

#include <cstdio>

int* p = new int[100000]();
int PartationsP(int n)
{
    int res = 0,k = 1,a = 2,b = 1,s = 1;
    while (n >= a){
        res += s*(p[n-a] + p[n-b]);
        a += 3*k+2;
        b += 3*k+1; 
        s *= -1;
        k += 1;
    }
    res += (n >= b)? s*p[n-b]:0;
    return res % 1000000;
}

int main()
{
    p[0] = 1;
    p[1] = 1;
    int n = 1;
    do{
        n++;
        p[n] = PartationsP(n);
    }while (p[n] != 0);
    printf("%d\n",n);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章