zoukankan      html  css  js  c++  java
  • 洛谷P1147 连续自然数和

    题目解法:
    这题是个大水题,但是我们看到了两种解法:
    法一①:考虑前缀和做法。
    首先我们读题,发现其要求的是连续自然数和。连续自然数和,那么我们可以用前缀和来处理这些自然数的和。于是我们得到了一个显然的做法:(30pts)直接枚举。
    Code:

    #include<iostream>
    #include<cstdio>
    #define ll long long
    #define maxn 2000001
    using namespace std;
    int m,s[maxn];
    int main(){
        cin>>m;
        s[0]=0;
        for(int i=1;i<=m;i++){
            s[i]=s[i-1]+i;
        }
        for(int i=1;i<=m;i++){
            for(int j=1;j<i;j++){
                if(s[i]-s[j-1]==m){
                    cout<<j<<" "<<i<<endl;
                }
            }
        }
        return 0;
    }

    法一②:考虑前缀和做法的优化版本。我们发现,在上一个阶段的代码上,我们可以对内层循环j做一些处理。比如,我们可以对这个j进行二分答案,得到一个j,然后从i到j,就是答案要求的区间。
    Code:

    #include<iostream>
    #include<cstdio>
    #define maxn 2000001
    #define int long long
    using namespace std;
    int m,s[maxn];
    int check(int ll,int rr,int k){
        if(ll>rr) return -1;
        int mid=(ll+rr)/2;
        if(s[mid]-k==m) return mid;
        else if(s[mid]-k>m) check(ll,mid-1,k);
        else if(s[mid]-k<m) check(mid+1,rr,k);
    }
    main(){
        cin>>m;
        s[0]=0;
        for(int i=1;i<=m;i++){
            s[i]=s[i-1]+i;
        }
        for(int i=1;i<=m;i++){
        /*    for(int j=1;j<i;j++){
                if(s[i]-s[j-1]==m){
                    cout<<j<<" "<<i<<endl;
                }
            }*/
            int k=check(i+1,m,s[i-1]);
            if(k!=-1) cout<<i<<" "<<k<<endl;
        }
        return 0;
    }

    法二:考虑数学方法。
    在洛谷标签上,我们可以发现一个标签:数学,数论。那么这就代表了数学解法。观察这道题,我们发现,这些数字的差值都是一样的,这其实是个等差数列。
    对于每个等差数列,我们有个等差数列求和公式,直接带入这个公式就可以A了这个题。
    Code详见Luogu题解。

  • 相关阅读:
    [翻译]关于堆和堆栈
    sql 字符+数值 混合排序 lcs
    证明DataReader分页的可行性 lcs
    谈谈我对小公司、大公司及个人成长的见解 lcs
    sina 通用js代码说明 lcs
    Linux系统下生成证书 https证书
    【转】51单片机外部中断的C51编程
    【转】如何建立个人网站
    【转】关于C51的中断编程[原创]
    【转】毫不费力:破解加密PDF文档就使用这两三招
  • 原文地址:https://www.cnblogs.com/kenlig/p/9822590.html
Copyright © 2011-2022 走看看