题目描述
对一个给定的自然数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 <iostream>
#include<math.h>
#include<algorithm>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
数学归纳法
//int main()
//{
// int m;
// cin>>m;
// for(int k2=sqrt(2*m);k2>1;k2--)
// {
// if(2*m%k2==0&&(k2+2*m/k2)%2==1)
// {
// int k1=2*m/k2;
// cout<<(k1-k2+1)/2<<" "<<(k1+k2-1)/2<<endl;
// }
// }
// return 0;
//}
暴力枚举法
//int main()
//{
// int m;
// cin>>m;
// int i,j;
// for(i=1;i<=m/2;i++)
// {
// int sum=0;
// for(j=i;j<=m;j++)
// {
// sum+=j;
// if(sum>=m)
// break;
// }
// if(sum==m)
// cout<<i<<" "<<j<<endl;
// }
// return 0;
//}
//尺取法 双指针
int main()
{
int m;
cin>>m;
int i=1,j=2;
int sum=3;
for(i=1,j=2;i<=m/2;)
{
if(sum==m)
{
cout<<i<<" "<<j<<endl;
sum-=i;
i++;
}
if(sum<m)
{
j++;
sum+=j;
}
if(sum>m)
{
sum-=i;
i++;
}
}
return 0;
}