码迷,mamicode.com
首页 > 其他好文 > 详细

高斯求和等差数列前缀和(洛谷1147 连续自然数和)

时间:2017-05-30 16:12:50      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:turn   c++   ++   高斯   排列   思路   判断   pre   ==   

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

例子:1998+1999+2000+2001+2002 = 10000,所以从1998到2002的一个自然数段为M=10000的一个解。

输入格式:

包含一个整数的单独一行给出M的值(10 <= M <= 2,000,000)。

输出格式:

每行两个自然数,给出一个满足条件的连续自然数段中的第一个数和最后一个数,两数之间用一个空格隔开,所有输出行的第一个按从小到大的升序排列,对于给定的输入数据,保证至少有一个解。

输入样例#1:
combo.in
10000
输出样例#1:
combo.out
18 142 
297 328 
388 412 
1998 2002
这是我用前缀和计算的代码:
#include<bits/stdc++.h>
#define LL long long
using namespace std;

LL s[2000000];

int main()
{
   LL n;
   cin>>n;
   for(LL i=1;i<=2000000;i++)
     s[i]=s[i-1]+i;
   for(LL i=1;i<=2000000;i++)
   {
      if(i<n)
      {
	     for(LL j=i+2;j<=2000000;j++)
	       if(s[j]-s[i]==n)
	         cout<<i+1<<" "<<j<<endl;
	        else
	          if(s[j]-s[i]>n)
	            break;
	  }
	  else break;
   }
   return 0;
}

 以下为洛谷一位大神的思路:

整个题就是反向的一个等差数列求和

给出M,有等差数列求和公式得:设区间[x,y]上M=(x+y)*(x-y+1)/2 顺便提一下 x-y+1 为自然数个数

化简得到 y方-y=x方+x-2*M;进一步两边同时加一个1/4 可得 (y-1/2)方=(x+1/2)方-2*M;

于是两边开方 有y=根号下((x+1/2)方-2*M)+1/2;

那么我们就枚举x i=1;i<=M/2;i++ 因为至少是两个数相加所以枚举到一半即可;

可以算出每一个x对应的y 只需判断其是否为整数 如果是那么合题输出一组;

由于原大神的代码和讲解不符合,所以我就放上我自己的代码了(orz冯豫川)

#include<bits/stdc++.h>
using namespace std;
int main()
{
   LL n;
   cin>>n;
   for(int i=1;i<n;i++)
   {
      double h=sqrt((i+0.5)*(i+0.5)-2*n)+0.5;
      if(int(h)==h)
        cout<<int(h)<<" "<<i<<endl;
   }
   return 0;
}

 

数学方法代码简洁了很多不知道大家有没有发现。

高斯求和等差数列前缀和(洛谷1147 连续自然数和)

标签:turn   c++   ++   高斯   排列   思路   判断   pre   ==   

原文地址:http://www.cnblogs.com/foreverpiano/p/6920158.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!