洛谷 P1147 连续自然数和

题目描述

对一个给定的自然数M,求出所有的连续的自然数段,这些连续的自然数段中的全部数之和为M。

例子:1998+1999+2000+2001+2002 = 10000,所以从1998到2002的一个自然数段为M=10000的一个解。

输入输出格式

输入格式:

 

包含一个整数的单独一行给出M的值(10 <= M <= 2,000,000)。

 

输出格式:

 

每行两个自然数,给出一个满足条件的连续自然数段中的第一个数和最后一个数,两数之间用一个空格隔开,所有输出行的第一个按从小到大的升序排列,对于给定的输入数据,保证至少有一个解。

 

输入输出样例

输入样例#1: 复制
10000
输出样例#1: 复制
18 142 
297 328 
388 412 
1998 2002
#include<map>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
map<long long,int>ma;
int M;
long long sum[2000010];
int main(){
    scanf("%d",&M);
    for(int i=1;i<=M;i++)
        sum[i]=sum[i-1]+i,ma[sum[i]]=i;
    for(int i=1;i<=M;i++)
        if(ma[sum[i]+M])
            if(ma[sum[i]+M]-i-1>0)
                cout<<i+1<<" "<<ma[sum[i]+M]<<endl;
}
85分暴力

思路:改成二分就快多了。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int M;
int l,r,mid;
long long sum[2000010];
int find(long long x){
    l=1;r=M;
    while(l<=r){
        mid=(l+r)/2;
        if(sum[mid]<x)    l=mid+1;
        else r=mid-1;
    }
    if(sum[l]==x)    return l;
    else return 0;
}
int main(){
    scanf("%d",&M);
    for(int i=1;i<=M;i++)
        sum[i]=sum[i-1]+i;
    for(int i=1;i<=M;i++){
        int x=find(sum[i]+M);
        if(x&&x-i-1>0)
            cout<<i+1<<" "<<x<<endl;
    }
}
 
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
原文地址:https://www.cnblogs.com/cangT-Tlan/p/7859321.html