裸的前缀和啊。
(mathcal{O}(n^2)) 枚举有可能的答案,利用前缀和的性质维护答案即可
但是 (m) 的范围很大,需要加入剪枝:
- (i,j) 枚举的范围 [1,m] 就好了,因为若 (i,j) 大于 (m) 那么必然得不到答案;
- 找到一个答案就退出一次循环,因为不可能再找到以 (i) 为左端点的另一个答案;
- 如果当前情况已经大于 (m) 就退出一次循环,因为既然 [i,j] 都大于 (m) ,那么 [i,j+?] 也必然大于 (m) 。
之所以可以这样干是因为要求找的是单调上升自然数连续数列。
另外,j 每次的循环范围应从 i+1 开始,因为若 (j<i) ,那么一定得不到答案(每次相减都会是负数)。这样做既加快了速度,也可以保证答案不重不漏。
#include <iostream>
#include <stdio.h>
using namespace std;
int pre[20000010],m;
int main()
{
cin>>m;
for(int i=1;i<=m;i++) pre[i]=i+pre[i-1];
for(int i=1;i<=m-1;i++)
for(int j=i+1;j<=m;j++)
{
if(pre[j]-pre[i-1]==m)
{
cout<<i<<" "<<j<<endl;
break;
}
if(pre[j]-pre[i-1]>m) break;
}
return 0;
}