Partition
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 941 Accepted Submission(s): 539
Problem Description
How many ways can the numbers 1 to 15 be added together to make 15? The technical term for what you are asking is the "number of partition" which is often called P(n). A partition of n is a collection of positive integers (not necessarily distinct) whose sum equals n.
Now, I will give you a number n, and please tell me P(n) mod 1000000007.
Now, I will give you a number n, and please tell me P(n) mod 1000000007.
Input
The first line contains a number T(1 ≤ T ≤ 100), which is the number of the case number. The next T lines, each line contains a number n(1 ≤ n ≤ 10
5) you need to consider.
Output
For each n, output P(n) in a single line.
Sample Input
4 5 11 15 19
Sample Output
7 56 176 490
Source
利用母函数做整数拆分,利用五边形定理进行优化,能够优化出n^1.5的算法
有一个讲的很好的家伙,我就不重新写了
别人的讲解
有一个讲的很好的家伙,我就不重新写了
别人的讲解
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#define MAX 100007
#define MOD (1000000007LL)
using namespace std;
typedef long long LL;
LL five ( LL x )
{
return x*(3LL*x-1LL)/2LL;
}
LL dp[MAX];
int n,t;
int main ( )
{
memset ( dp , 0 , sizeof ( dp ) );
dp[0] = 1;
for ( int i = 1 ; i < MAX ; i++ )
for ( int j = 1 ;; j++ )
{
LL k = five(j);
if ( k > i ) break;
if ( j&1 )
dp[i] = dp[i] + dp[i-k];
else dp[i] = dp[i] - dp[i-k];
dp[i] = ( dp[i]%MOD + MOD ) %MOD;
k = five ( -1*j );
if ( k > i ) break;
if ( j&1 )
dp[i] = dp[i] + dp[i-k];
else dp[i] = dp[i] - dp[i-k];
dp[i] = ( dp[i]%MOD + MOD ) %MOD;
}
scanf ( "%d" , &t );
while ( t-- )
{
scanf ( "%d" , &n );
printf ( "%I64d\n" , dp[n] );
}
}