您的位置:首页 > 其它

hdu4651

2016-07-02 11:03 218 查看
(OI)选手”——报考杭州电子科技大学!

Partition

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1099    Accepted Submission(s): 648


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.

 

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 ≤ 105) 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

2013 Multi-University Training Contest 5
 

Recommend

zhuyuanchen520   |   We have carefully selected several similar problems for you:  5717 5716 5715 5714 5713 

题意:数字k写成和的形式,有多少种情况例如:

4 = {4}  {1,3} {2,2} {1,1,2} {1,1,1,1} 共五种情况

在51 node上看到的这道题,标签是dp,但是确实是数学公式题,欧拉函数的倒数是整数的划分的母函数

 


   其中

为k的分割函数。  
 至于问什么是,我也不知道--


欧拉函数及其展开式是这样的

 



 


这个展开式的指数广义五边形数  为1 2 5 7 12 15 22 26

  ↓



为五边形数  1,
5, 12, 22, 35, 51, 70, ...


 


                                

把欧拉函数乘到右边展开  



#include <iostream>

using namespace std;

const int maxn=1e5+50,mod=1e9+7;

int dp[maxn],temp[maxn];

void init()

{

    int t=1000;

    for(int i=-1000;i<=1000;i++)

    {

        temp[i+t]=i*(3*i-1)/2;

    }

    dp[0]=1;

    for(int i=1;i<maxn;i++)

    {

        dp[i]=0;

        for(int j=1;j<=i;j++)

        {

            if(temp[t+j]<=i)

            {

                if(j&1)dp[i]+=dp[i-temp[t+j]];

                else

                    dp[i]-=dp[i-temp[t+j]];

            }

            else

                break;

                dp[i]=(dp[i]%mod+mod)%mod;

            if(temp[t-j]<=i)

            {

                if(j&1)

                    dp[i]+=dp[i-temp[t-j]];

                else

                    dp[i]-=dp[i-temp[t-j]];

            }

            else

                break;

        }

          dp[i]=(dp[i]%mod+mod)%mod;

    }

}

int main()

{

    int t;

    int n;

    cin>>t;

    init();

    while(t--)

    {

        cin>>n;

        cout<<dp
<<endl;

    }

    return 0;

}
在 n>0 时,等式右侧的系数均为0,比较等式二侧的系数,可得
 



 

因此可得到分割函数p(n)的递归式:



#include <iostream>

using namespace std;
const int maxn=1e5+50,mod=1e9+7;
int dp[maxn],temp[maxn];
void init()
{
int t=1000;
for(int i=-1000;i<=1000;i++)
{
temp[i+t]=i*(3*i-1)/2;
}
dp[0]=1;
for(int i=1;i<maxn;i++)
{
dp[i]=0;

for(int j=1;j<=i;j++)
{
if(temp[t+j]<=i)
{
if(j&1)dp[i]+=dp[i-temp[t+j]];
else
dp[i]-=dp[i-temp[t+j]];
}
else
break;
dp[i]=(dp[i]%mod+mod)%mod;
if(temp[t-j]<=i)
{
if(j&1)
dp[i]+=dp[i-temp[t-j]];
else
dp[i]-=dp[i-temp[t-j]];
}
else
break;

}
dp[i]=(dp[i]%mod+mod)%mod;
}
}
int main()
{
int t;
int n;
cin>>t;
init();
while(t--)
{
cin>>n;
cout<<dp
<<endl;
}
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: