题目:http://acm.hdu.edu.cn/showproblem.php?pid=4651
题目大意:将一个数n拆分成几个数相加,问有多少种方案?
思路:
参见五边形定理。。 http://en.wikipedia.org/wiki/Partition_(number_theory)
n 的上限是10^5,普通二维的公式时间空间都不行。。后来问了一下,原来做出来的都是直接上google,然后在维基上找到的,可怜我们用baidu,死活找不到,以后长姿势了,果断google啊。。 T^T
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MOD = 1e9 + 7;
const int MAXN = 100111;
int d[MAXN];
void init()
{
d[0] = 1;
d[1] = 1;
for(int i = 2;i<=100000;i++)
{
d[i] = 0;
int flag = 1;
int add1,add2;
for(int j = 1;;j++)
{
int pos1 = i - j*(3*j-1)/2;
int pos2 = i - j*(3*j+1)/2;
if(pos1<0) break;
add1 = d[pos1];
if(pos2<0) add2 = 0;
else add2 = d[pos2];
d[i] = (d[i]+flag*(add1 + add2)%MOD)%MOD;
flag *= -1;
}
d[i]=(d[i]+MOD)%MOD;
}
}
int main()
{
init();
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
printf("%d\n",d[n]);
}
return 0;
}
/* d[i][j] = d[i][j-1] + d[i-j][j] , 二维的公式,放苹果问题,d[i][j]表示将i分为j个数的个数,分两种情况:
(1)至少有一个为0,那么就是d[i][j-1]。(2)所有数都至少为1,就是d[i-j][j]。*/