4447: 【基础】连续自然数和(2120)

内存限制:128 MB 时间限制:1.000 S
评测方式:文本比较 命题人:
提交:1 解决:1

题目描述

对一个给定的自然数 lns="http://www.w3.org/1998/Math/MathML"> ,求出所有的连续的自然数段,这些连续的自然数段中的全部数之和为 lns="http://www.w3.org/1998/Math/MathML"> 。

例子:lns="http://www.w3.org/1998/Math/MathML">1998+1999+2000+2001+2002=10000,所以从 lns="http://www.w3.org/1998/Math/MathML">1998 到 lns="http://www.w3.org/1998/Math/MathML">2002 的一个自然数段为 lns="http://www.w3.org/1998/Math/MathML">=10000 的一个解。

输入

包含一个整数的单独一行给出 lns="http://www.w3.org/1998/Math/MathML"> 的值(lns="http://www.w3.org/1998/Math/MathML">102,000,000 )。

输出

每行两个自然数,给出一个满足条件的连续自然数段中的第一个数和最后一个数,两数之间用一个空格隔开;

所有输出行的第一个按从小到大的升序排列,对于给定的输入数据,保证至少有一个解。

样例输入 复制

10000

样例输出 复制

18 142
297 328
388 412
1998 2002

提示

#include<bits/stdc++.h>
using namespace std;
const int N=1000010;
long long b[N],m,n=1;
int check(int k,int mid) {
    if(b[k+mid]-b[k-1]==m) return 0;
    else if(b[k+mid]-b[k-1]<m) return -1;
    else return 1;
}
int main(){
    cin>>m;
    while(1) {
    	b[n]=b[n-1]+n;
    	if (n>=(m/2+1)) break;
    	n++;
	}
	for(long long i=1;i<=n;i++) {
		long long l=1,r=n-i,mid;
		while(l<=r) {
			mid=l+r>>1;
			if (check(i,mid)==0) {
				cout<<i<<" "<<i+mid<<endl;
				break;
			}
            if(check(i,mid)==1) {
				r=mid-1;
			}else if(check(i,mid)==-1) { 
				l=mid+1;
			}
		}
	}
	return 0;
}