整数拆分种类(五边形数定理)

  
  

题目: 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 ≤ 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 题意: T组样例 问n能拆分成几种 突然觉得下面这个题目更好看懂! "Well, it seems the first problem is too easy. I will let you know how foolish you are later." feng5166 says. "The second problem is, given an positive integer N, we define an equation like this: N=a[1]+a[2]+a[3]+...+a[m]; a[i]>0,1<=m<=N; My question is how many different equations you can find for a given N. For example, assume N is 4, we can find: 4 = 4; 4 = 3 + 1; 4 = 2 + 2; 4 = 2 + 1 + 1; 4 = 1 + 1 + 1 + 1; so the result is 5 when N is 4. Note that "4 = 3 + 1" and "4 = 1 + 3" is the same in this problem. Now, you do it!" Input The input contains several test cases. Each test case contains a positive integer N(1<=N<=120) which is mentioned above. The input is terminated by the end of file. Output For each test case, you have to output a line contains an integer P which indicate the different equations you have found. Sample Input 4 10 20 Sample Output 5 42 627

#include <iostream>  
#include <string.h>  
#include <stdio.h>  
#include <algorithm>
using namespace std;   
  
const int N=100005;  
const __int64 MOD=1000000007;  
  
__int64 ans[N],tmp[N];  
  
void Init()  //模板模板
{  
    int t=1000;  
    for(int i=-1000;i<=1000;i++)  
        tmp[i+t]=i*(3*i-1)/2;  
    ans[0]=1;  
    for(int i=1;i<N;i++)  
    {  
        ans[i]=0;  
        for(int j=1;j<=i;j++)  
        {  
            if(tmp[j+t]<=i)  
            {  
                if(j&1)  ans[i]+=ans[i-tmp[j+t]];  
                else     ans[i]-=ans[i-tmp[j+t]];  
            }  
            else break;  
            ans[i]=(ans[i]%MOD+MOD)%MOD;  
            if(tmp[t-j]<=i)  
            {  
                if(j&1) ans[i]+=ans[i-tmp[t-j]];  
                else    ans[i]-=ans[i-tmp[t-j]];  
            }  
            else break;  
        }  
        ans[i]=(ans[i]%MOD+MOD)%MOD;  
    }  
}  
int main()  
{  
    int t,n;  
    Init();  
    cin>>t;  
    while(t--)  
    {  
        scanf("%d", &n);
        printf("%I64d\n", ans[n]);
    }  
    return 0;  
}  


如果数据较小又容易t的话就把N减小t减小吧!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值