洛谷Oj-连续自然数和-前缀和 + 二分查找

来源:互联网 发布:sql developer查询 编辑:程序博客网 时间:2024/06/08 08:25

问题描述:
对一个给定的自然数M,求出所有的连续的自然数段,这些连续的自然数段中的全部数之和为M。
例子:1998+1999+2000+2001+2002 = 10000,所以从1998到2002的一个自然数段为M=10000的一个解。
AC代码:

long long num[2000010],sum[2000010];//数组sum用来做前缀和int bsearch(int l,int r,long long key)//二分查找模板{    int mid;    while(l <= r)    {        mid = (l + r) / 2;        if(sum[mid] == key)            return mid;        else if(sum[mid] > key)            r = mid-1;        else            l = mid+1;    }    return -1;//如果没找到就返回-1}int main(){    int m;    cin >> m;//输入    for(int i = 1; i <= m; ++i)    {        num[i] = i;        sum[i] = sum[i - 1] + num[i];//预处理前缀和    }//   for(int i = 1; i <= m - 1; ++i)//初始代码,时间复杂度O(n^2),TLE//        for(int j = i; j <= m - 1; ++j)//            if(sum[j] - sum[i - 1] == m)//看到这个等式,马上想到可以优化//              printf("%d %d\n",i,j);    int ans;//记录二分查找函数的返回值,避免重复调用    for(int i = 1; i <= m - 1; ++i)    {        ans = bsearch(i,m,m + sum[i - 1]);//这里前缀和是严格递增的,故可以使用二分查找,优化后时间复杂度为O(nlogn)        if(ans != -1)//找到了            printf("%d %d\n",i,ans);    }    return 0;}

解决方法:
连续自然数 =》 区间段 =》 前缀和
sum[j] - sum[i - 1] == m =》变形为sum[j] == sum[i - 1] + m=》如果能在sum数组中找到sum[j],则满足题意

原创粉丝点击