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]
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
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 . 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;
}