点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2000010;
int n;
long long a[N];
int bsearch(long long target,int n)
{
int l=1,r=n;
while(l<r){
int mid=l+(r-l)/2;
if(a[mid]>=target) r=mid;
else l=mid+1;
}
return l;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n;
//连续自然数之和的前缀和数组
for(int i=1;i<=n;i++) a[i]=a[i-1]+i;
for(int i=1;i<=n;i++){
long long target=a[i-1]+n;
if(target > a[n]) continue;
int t=bsearch(target,n);
if(a[t]-a[i-1]==n&&t<=n){
if(i!=t) cout<<i<<" "<<t<<endl;
}
}
return 0;
}
①二分的核心就是查找了,因此关键不在于二分而在于查找,确定二分查找的规律,或者确定查找什么值,然后查找即可,严格递增还可以直接用lower_bound查找
②然后2,000,000,10……6次方的查找并不大,可以接受,cpu一秒大概在10……8次运算
③然后还要小心爆int,可能单个存储的数值不会爆,但前缀和可能是爆的
④利用前缀和确定对应数的方法,利用前缀和公式a[j]-a[i-1]=n,可以得出a[j]的值,然后查找对应的j的下标