关于连续自然数和问题的探讨

题目描述:
对一个给定的自然数M,求出所有的连续的自然数段,这些连续的自然数段中的全部数之和为M。

分析:
(1)常见的方法是暴力去寻找,或者是打表记录下来,不过很可惜,这样做的时间复杂度是O(n^2)

(2)利用求和公式和求根公式:

设存在连续自然数,首项为A1,项数为m,即

A1+A2+...+Am=M

得到求和公式

A1*m+m*(m-1)/2=M

整理得到

m^2+(2*A1-1)*m-2M=0

很明显,这是一个关于m的一元二次方程,利用求根公式

m=(-b+sqrt(b^2-4*a*c)))/(2*a)

带入得:

m=(1-2*A1+sqrt((2*A1-1)^2+8*M))/2

因为要满足m为整数,那么就需要满足两个条件:

(1)sqrt((2*A1-1)^2+8*M)是整数;

(2)整个分子为偶数;

如果这两个条件都满足,那么就会存在m,因此可以开一个循环,从1遍历到n/2(想想为什么),对于每个i,当做A1来处理,看求出来的m是否为整数即可。

#include<iostream>
#include<cmath> 
#include<cstdio>
using namespace std;
int main()
{
    int n,tt=1;
    while(cin>>n)
    {
        printf("Case %d:\n",tt++);
        for(int i=0;i<n/2;i++)
        {
            int a=i;
            int w=(2*a-1)*(2*a-1)+8*n;
            int k=(int)sqrt(w);
            int m=k-2*a+1;
            if(k*k!=w)
              continue;
            else if(m%2)
              continue;
            else
              cout<<i<<" "<<i+m/2-1<<endl;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值