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
", l, r);
r++;
}
return 0;
}