连续整数固定和(C百例 & 51nod 1138)

连续整数固定和(C百例 & 51nod 1138)_第1张图片

书上讲了一种提高效率的方法。原始算法:用i遍历1到n-1,如果i到j的和等于n那么就输出相应的结果。我们可以发现当sum(i,j)=n时,继续j++,sum+=j,计算的sum肯定是大于n的,于是便在sum(i,j)=n输出结果后,sum-=i,再继续sum+=j等后续工作,这样避免了无用功。

#include <iostream>
#include<cstdio>
using namespace std;
void f(int x){
    int i=1,j=2,sum=i;
    while(i<=x/2){
    	if(sum>=x)break;
    	else if(sum<x){
    		for(;j<=x/2+1;j++){
    			sum+=j;
    			if(sum==x){
    				printf("%d~%d\n",i,j);
    				sum-=i;
    				i++;
    				if(i>x/2)break;
    			}
    			else if(sum>x){
    				do{
    					sum-=i;
    					i++;
    					if(sum==x){
    						printf("%d~%d\n",i,j);
    						break;
    					}
    					else if(sum<x)break;
    				}while(i<=x/2&&sum>x);
    			}
    		}
    	}
    }
}
int main()
{
    int n;
    while(cin>>n){
        f(n);
    }
    return 0;
}

在51nod也发现了相关的问题:

http://www.51nod.com/onlineJudge/solutionRank.html#!problemId=1138

给出一个正整数N,将N写为若干个连续数字和的形式(长度 >= 2)。例如N = 15,可以写为1 + 2 + 3 + 4 + 5,也可以写为4 + 5 + 6,或7 + 8。如果不能写为若干个连续整数的和,则输出No Solution。

Input
输入1个数N(3 <= N <= 10^9)。
Output
输出连续整数中的第1个数,如果有多个按照递增序排列,如果不能分解为若干个连续整数的和,则输出No Solution。

分析:设m是连续的数字个数,那么第一位数字一定满足:,这是一个减函数,所以可以确定对应的查找范围。同时,当m时偶数时,n%m=m/2;当m是奇数时,。

#include <iostream>
#include <cstdio>
using namespace std;
int midfind(int n){
    int l=2,r=n/2,mid,ans=0;
    while(l<=r){
        mid=(l+r)>>1;
        if(n/mid-mid/2>0){
            ans=mid;
            l=mid+1;
        }
        else r=mid-1;
    }
    return ans;
}
int main()
{
    //freopen("cin.txt","r",stdin);
    int n;
    while(cin>>n){
        int len=midfind(n);
        bool flag=0;
        for(int i=len;i>=2;i--){
            if((i&1)&&n%i==0){
                printf("%d\n",n/i-i/2);
                flag=1;
            }
            else if(((i&1)==0)&&n%i==i/2){
                    printf("%d\n",n/i-i/2+1);
                    flag=1;
            }
        }
        if(!flag) puts("No Solution");
    }
    return 0;
}

另外,我&的优先级很低啊,甚至小于"==",所以书写的时候注意加括号。

你可能感兴趣的:(技巧)