HDOJ 2058 The sum problem [效率分析]

题目的意思并不难理解:输入两个整数M,NN, M( 1 <= N, M <= 1000000000),如果在范围[1,M]内连续整数的和为N,按从小到大次序输出所有这样的连续段,当输入的M,N都为0时结束。

譬如:
Sample Input

20 10
50 30
0 0

Sample Output

[1,4]
[10,10]

[4,8]
[6,9]
[9,11]
[30,30]


因为M,N的范围比较大,一般的算法很容易超时,所以在这里,时间效率尤其重要。


方法一:回溯暴力求解

该方法是看到题目后最容易想到的,运行结果也正确,但提交时,严重超时。

代码如下:



后来将两个for循环语句都再增加一条限制:i<=m/2和j<=m/2 结果还是一样。

Time Limit Exceeded 2058 1000MS248K349 BC+


方法二:求段长法


该方法来自严明超同学,我在这里稍微修改了一条语句,核心思想是利用等差数列求和公式:(d+1)*d/2+d*(a-1)=n,其中d为段长,a为等差首项,n为d项连续整数数列的和。

因为一开始段长要最大,所以a取1,根据该公式可求得:d=(int)(sqrt(0.25+2*n)-0.5)。然后段长d逐步减1(即d--),利用公式a=(2*n/d-d+1)/2 分别求得首项a的值,并用a==(int)a判定首项a是否为整数,如果是则输出结果,不是则跳过,然后d--,当d=0时,跳出循环,打印回车,结束本次求解。

代码如下:

 

 

Accepted 2058 62MS256K450 BC++

 

AC成功,时间为62MS。

 

 

方法三:公式推理法

 

具体思路是:
1、假设连续的整数段为 (x+1)+(x+2)+(x+3)+...+(x+i) 其中x=0,1,2,3....

2、设N=(x+1)+(x+2)+(x+3)+...+(x+i) => N-(1+2+3+..+i)=x*i 化解后得:N-(i+1)*i/2=x*i

3、因为x要为整数,所以得出最终判定条件:(N-(i+1)*i/2)%i==0

4、根据2求得x=n/2-(1+i)/2

5、则连续整数段第一项x+1=n/i-(i-1)/2   最后项x+i=n/2+i/2

6、又因为x+1>=0  x+i<=M 则n/i-(i-1)/2>=0,n/2+i/2<=M分别作为for循环的条件,经过测试位置不可互换,也可以根据数学推理来论证两个条件该如何选择。

 

代码如下:

 

 

Accepted 2058 46MS184K443 BC
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值