求和问题

问题来源:http://acm.hdu.edu.cn/showproblem.php?pid=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]

问题解读:

    有一个序列1,2,3,……n,我们输入n和m,n表示连续等差序列的最大数,m表示我们要求的和值,我们需要列举出序列中符合连续几项的和等于m的情况。

问题分析:

    首先,我们可以发现,这是一个等差序列,我们可以使用等差序列的求和公式(a+b)*i/2=m,(a表示首项,b表示末项,i表示项数)

    由于b=a+i-1

    可得(a+a+i-1)*i/2=m

    得出 a = m / i - (i-1) / 2

    因此,我的第一次提交的代码如下:


    不过,超时了。

    我想,应该是i=n这一步的影响。如果,我把n输入一个很大的数,而m很小的话,循环还在一直持续着,但后面的内容都是不可能输出的。因此,接下来要做的就是减少循环的次数。

    可以从a>=1入手。因为a = m / i - (i-1) / 2>=1,化简可得2m>=i^2+i >=i^b2,所以可得i<=\sqrt{2m} 。i的范围也就缩小了,这样循环的次数也就减少了。

    修改后的代码如下:

import java.util.Scanner;

public class Test_2058 {

public static void main (String args[]) {

Scanner in = new Scanner(System.in);

while(in.hasNext()) {

Long n = in.nextLong();

Long m = in.nextLong();

if(n == 0 && m == 0)

break;

long a;

long b;

for(long i=(long)Math.sqrt(2*m);i>0;i--) {

a = m / i - (i-1) / 2;

b = a + i - 1;

if((a+b)*i == 2*m && a > 0 && b > 0)

System.out.println("["+a+","+b+"]");

}

System.out.println();

}

}

}

小结:

    在循环时,要尽量地优化,减少不必要的循环,提高时间效率。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。