您的位置:首页 > 理论基础 > 计算机网络

http://acm.hdu.edu.cn/showproblem.php?pid=4477

2013-03-10 21:22 106 查看
题目:

We have a rope whose length is L. We will cut the rope into two or more parts, the length of each part must be an integer, and no two parts have the same length.
  Your task is to calculate there exists how many results after the cutting. We say two results are different if and only if there is at least one part, which we can find in one result but can not find in the other result.

样例:

输入:

3
2
3
6
输出:

0
1
3
思路:

首先考虑,若分解成k段,则n的值至少为1+2+3+4+...+k=(k+1)*k/2

所以本题k的最大值为315

考虑dp[k]
表示长度为n的线段分解成k段的方案数。

其中分为两种情况

  k段均大于一,则将每段的长度减1后,与dp[k][n-k]的方案数相同。

  k段中有一段是1,则去掉这段长度为1的,有k-1段,且长度均大于一,与dp[k-1][n-k]方案数相同,这是k>2的情况。特殊的,k=2时,n=1,2无解为0,n>2方案为(1,n-1),即1。

代码:

#include <cstdio>
#include <cstring>
using namespace std;
#define N 50000
int w = 1000000;
int dp[2][N + 1];
int sum[N + 1];
int main()
{
//freopen("Input.txt","r",stdin);
// freopen("Output.txt","w",stdout);
for(int i = 3;i <= N;i ++)
sum[i] = dp[0][i] = dp[0][i - 2] + 1;
for(int k = 3;k < 316;k ++)
{
int *p1 = dp[k & 1],*p2 = dp[(k + 1) & 1];
for(int i = k * (k + 1) / 2 - 1;i > 0;i --) p1[i] = 0;
for(int i = k * (k + 1) / 2;i <= N;i ++)
{
p1[i] = p1[i - k] + p2[i - k];
if(p1[i] >= w)
p1[i] -= w;
sum[i] += p1[i];
if(sum[i] >= w )
sum[i] -= w;
}
}
int t;
scanf("%d",&t);
while(t --)
{
int n;
scanf("%d",&n);
printf("%d\n",sum
);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: