P1147 连续自然数和

P1147 连续自然数和

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


Solution

两点问题
弄两个点 \(l,r\) , 因为前缀和有单调性, 所以我们不断地调整 \(l , r\) 来接近所给数
当发现调整完一次后刚好等于所给数, 输出即可, 复杂度 \(O(n)\)

这个题还可以用等差数列求和来优化到 \(O(\sqrt{N})\)

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<climits>
typedef long long LL;
using namespace std;
LL RD(){
    LL out = 0,flag = 1;char c = getchar();
    while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
    while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
    return flag * out;
    }
const LL maxn = 2000019;
LL num, sum[maxn];
int main(){
	num = RD();
	for(LL i = 1;i <= num + 19;i++)sum[i] = sum[i - 1] + i;
	LL l = 1, r = 2;
	while(l < r && r <= num){
		while(sum[r] - sum[l - 1] < num && r <= num && l < r - 1)r++;
		while(sum[r] - sum[l - 1] > num && r <= num && l < r - 1)l++;
		if(sum[r] - sum[l - 1] == num)printf("%lld %lld\n", l, r);
		r++;
		}
	return 0;
	}
posted @ 2018-08-20 20:15  Tony_Double_Sky  阅读(253)  评论(0编辑  收藏  举报