Project Euler:Problem 78 Coin partitions

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.



没想到数值划分结果会那么大,按照前面的方法半天得不到结果。。。

看别人的题解知道了这个


The generating function for p(n) is given by:[5]

\sum_{n=0}^\infty p(n)x^n = \prod_{k=1}^\infty \left(\frac {1}{1-x^k} \right).

Expanding each factor on the right-hand side as a geometric series, we can rewrite it as

(1 +  x +  x 2 +  x 3 + ...)(1 +  x 2 +  x 4 +  x 6 + ...)(1 +  x 3 +  x 6 +  x 9 + ...) ....

The xn term in this product counts the number of ways to write

n =  a 1 + 2 a 2 + 3 a 3 + ... = (1 + 1 + ... + 1) + (2 + 2 + ... + 2) + (3 + 3 + ... + 3) + ...,

where each number i appears ai times. This is precisely the definition of a partition of n, so our product is the desired generating function. More generally, the generating function for the partitions of n into numbers from a set A can be found by taking only those terms in the product where k is an element of A. This result is due to Euler.

The formulation of Euler's generating function is a special case of a q-Pochhammer symbol and is similar to the product formulation of many modular forms, and specifically the Dedekind eta function.

The denominator of the product is Euler's function and can be written, by the pentagonal number theorem, as

(1-x)(1-x^2)(1-x^3) \dots = 1 - x - x^2 + x^5 + x^7 - x^{12} - x^{15} + x^{22} + x^{26} - \dots.

where the exponents of x on the right hand side are the generalized pentagonal numbers; i.e., numbers of the form ½m(3m − 1), where m is an integer. The signs in the summation alternate as (-1)^{m}. This theorem can be used to derive a recurrence for the partition function:

p( k) =  p( k − 1) +  p( k − 2) −  p( k − 5) −  p( k − 7) +  p( k − 12) +  p( k − 15) −  p( k − 22) − ...

where p(0) is taken to equal 1, and p(k) is taken to be zero for negative k.


#include <iostream>  
#include <vector>
using namespace std;

int main()
{
	vector<int>p;
	p.push_back(1);
	int n = 1;
	while (1)
	{
		int i = 0;
		int k = 1;
		p.push_back(0);

		while (k <= n)
		{
			int mark;
			if (i % 4 == 0 || i % 4 == 1)
				mark = 1;
			else
				mark = -1;
			p[n] += mark*p[n - k];
			p[n] %= 1000000;
			i++;

			int j = i / 2 + 1;
			if (i % 2 != 0)
				k = (3 * j*j + j) / 2;
			else
				k = (3 * j*j - j) / 2;
		}
		if (p[n] == 0)
			break;
		n++;
	}
	cout << n << endl;
	system("pause");
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值