杭电2058——The sum problem

杭电2058——The sum problem

原题链接
题的大意是:给定一个数列1、2、3、·········、N,找出所有符合条件的子数列,即子数列的各项之和等于M,,输入的测试用例有多组,输入N空格M,将符合的子数列按照 [p,q] 的格式输出。每个测试用例后面都跟一个空行。
第一次得到这种题,首先想到的就是最笨的办法:一个一个找,反正也不是自己算。于是很容易就有了代码:

# include 
int main (){
    int m,n,i,j,s;
    while (~scanf ("%d%d",&m,&n),n!=0 && m!=0){
        for (i=1;i<=n;i++){
            s=0;
            for (j=i;j<=n;j++){
                s=s+j;
                if (s>=n){
                    if (s==n){
                        printf ("[%d,%d]\n",i,j);
                    }
                    break;
                }
            }
        }
        printf ("\n");
    }
}

虽然嵌套的层数比较多,但是很容易理解。提交的时候,出现了(Time Limit Exceeded)这样的判断,也就是超时了,说明这个算法不行。
那怎么解决这个问题呢?
第一:先进行长度x上限的判断,代码如下:

        for (i=1,s=0;s<=n;i++){//···n代表输入的M(所求的和)
            s+=i;
        }
        x=i-1;//··············x代表长度

x最后减去了一是因为,经过for循环之后s肯定大于M,所以x减一,可以减少算数的步骤。

第二:筛选出符合要求的子数列;代码如下:

        for (i=x;i>=2;i--){//······让长度依次递减
            if (n%i==0){//·········如果平均数是整数
                p=n/i-i/2;
                q=n/i+i/2;//·········计算开始点和结束点(格式:[p,q])
            }
            else if (2*n%i==0){//·········如果平均数乘上2是整数
                p=n/i-i/2+1;
                q=n/i+i/2;//·········计算开始点和结束点(格式:[p,q])
            }
            else{
                continue;
            }
            t=(q-p+1)*(p+q)/2;//计算得到的数列的各元素之和,用于检验是否符合条件 
            if (t==n && p>0){
                printf ("[%d,%d]\n",p,q);
            }//·······如果检验成功就按格式输出
        }

最后进行整理:

# include 
int main (){
    int m,n,i,s,x,p,q,t;
    while (~scanf ("%d%d",&m,&n),m!=0 || n!=0){
        for (i=1,s=0;s<=n;i++){
            s+=i;
        }
        x=i-1;
        for (i=x;i>=2;i--){
            if (n%i==0){
                p=n/i-i/2;
                q=n/i+i/2;
            }
            else if (2*n%i==0){
                p=n/i-i/2+1;
                q=n/i+i/2;
            }
            else{
                continue;
            }
            t=(q-p+1)*(p+q)/2;
            if (t==n && p>0){
                printf ("[%d,%d]\n",p,q);
            }
        }
        printf ("[%d,%d]\n\n",n,n);//···输出本身的那一种情况
    }
    return 0;
}

如果有兴趣,期望能和大家一起交流。
这是我第一次发表文章,还望各位大神多多包涵!!!

你可能感兴趣的:(HDU,OJ)