The sum problem(hdu 2058)解题报告
Problem Description
Given a sequence 1,2,3,......N, your job is to calculate all the possible sub-sequences that the sum of the sub-sequence is M.
Input
Input contains multiple test cases. each case contains two integers N, M( 1 <= N, M <= 1000000000).input ends with N = M = 0.
Output
For each test case, print all the possible sub-sequence that its sum is M.The format is show in the sample below.print a blank line after each test case.
Sample Input
20 10
50 30
0 0
Sample Output
[1,4]
[10,10]
[4,8]
[6,9]
[9,11]
[30,30]
问题的意思就是给一个数m,求从1~N中有多少子序列的和等于m。
如20 10
有[1,4]
[10,10] (单个数也算一个子序列)
对50 30
有[4,8]
[6,9]
[9,11]
[30,30]
首先我们看高斯公式: 1+2+…+n=n*(n+1)/2
可以推导出 大于等于1的连续从a到b区间的和等于
sum(a,b)=sum(1,b) –sum(1,a-1) 将sum(b,a)定义为闭区间的和。令c=a-1
即: 1+2+…+b-(1+2+…+c)= (b^2+b)/2-(c^2+c)/2=(b-c)(b+c+1)/2
代入 sum(a,b)=m
可以得到: (b-c)(b+c+1)=m*2
对m*2进行因式分解,假设有2个因子,分别为x和y,且y>x。
有: b+c+1=y
b-c=x
解方程得: b=(y+x-1)/2 (1)
c=(y-x-1)/2 ,a=(y-x+1)/2 (2)
以 n=20,m=10 为例。 m*2的因子有 1*20,2*10,4*5
分别代入可以计算出
(1) : b=(20+1-1)/2=10 ,a=(20-1+1)/2=10
(2) : b=(10+2-1)/2=5.5 a=(10-2+1)/2=4.5 无效
(3) :b=(5+4-1)/2=4 a=(5-4+1)/2=1
由分析可以得出算法:
对于每个数m求出2*m的因子,对于每对因子,代入公式求出b,a若b为整数,且小于等于n,既为所求。
代码:
#include <string.h>
#include <stdio.h>
#include <math.h>
int main()
{
int i,j,n,m,t;
while(scanf("%d%d",&n,&m), m && n)
{
m*=2;
for(i=(int)sqrt((double)m);i>=2;i--)
{
if(m%i==0)
{
t=m/i+1-i;
if (t>=2 && t%2==0)
{
t>>=1;
if(t+i-1<=n)
printf("[%d,%d]\n",t,t+i-1);
}
}
}
m>>=1;
if(n>=m) printf("[%d,%d]\n",m,m);
printf("\n");
}
return 0;
}
个人网站:生活百科
本文版权所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。