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;
}


你可能感兴趣的:(HDU)