P1147 连续自然数之和(二分和前缀和

点击查看代码
#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的下标
posted @ 2025-11-21 11:47  AnoSky  阅读(3)  评论(0)    收藏  举报