首页 > 试题广场 >

连续整数求和

[编程题]连续整数求和
  • 热度指数:1051 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
给定一个正整数N,试求有多少组连续正整数满足所有数字之和为N? (1 <= N <= 10 ^ 9)

输入描述:
5


输出描述:
2
示例1

输入

5

输出

2

说明

5 = 5 = 2 + 3,共有两组连续整数([5],[2,3])求和后为 5。

备注:
解释: 5 = 5 = 2 + 3,共有两组连续整数([5],[2,3])求和后为 5。
题目中说给定一个正整数,测试用例中竟然给了一个0. 😣😣😣
发表于 2019-11-27 20:50:39 回复(0)
#include<bits/stdc++.h>
using namespace std;

int main()
{
    int n;
    while(cin>>n)
    {
        if(n==0)
        {
            cout<<1<<endl;
            continue;
        }
        int N=sqrt(2*n);
        int cnt=0;
        for(int i=1;i<=N;i++)
        {
            int tmp=n-(i-1)*i/2.0;
            if(tmp%i==0)
                cnt++;
        }
        cout<<cnt<<endl;
    }
    return 0;
}

发表于 2020-09-03 11:22:53 回复(0)
等差数列求和公式: (首项 + 末项) * 项数 / 2
因为题意是连续的数 故 末项 = 首项 + 项数 - 1
N = (首项 + 首项 + 项数 - 1) / 2 * 项数
   = (首项 + (项数 - 1) / 2) * 项数
N / 项数 = 首项 + (项数 - 1) / 2
根据上式对 N % 项数 分析可得
1. 当 项数 为奇数时,N % 项数 = 0
2. 当 项数 为偶数时,N % 项数 = 项数 / 2

已知 N > (项数 - 1) * 项数 / 2, 故
项数 < sqrt(2 * N) + 1
import java.util.Scanner;
 
public class Main{
        public static void main(String[] args){
        Scanner input = new Scanner(System.in);
        int N = input.nextInt();
        int ans = 1;
        int sqrtN = (int)Math.sqrt((double)N*2);//项数 < sqrt(2 * N) + 1
        for(int i = 2;i < sqrtN + 1;i++){
           if(i%2==1) {
               if (N % i == 0) ans++; //1. 当 项数 为奇数时,N % 项数 = 0
           }else {
               if (N % i == i/2) ans++;//2. 当 项数 为偶数时,N % 项数 = 项数 / 2
           }
        }
        System.out.println(ans);
    }
}


发表于 2020-07-22 12:59:21 回复(0)
public class Test{
    /**
     *
     * 总体思路为根据求和公式,得到一个二次函数。求解二次函数判断当前位置是否满足条件 
          *  所以只需要一次遍历就可以搞定
     *
     * 1:根据等比数列的求和公式得出 其中
     *      a1 表示数列第一个元素
     *      an 表示数列最后一个元素
     *      n表示数列的个数  并且 n = an - a1 + 1
     *      最终求和公式为:(a1 + an)n / 2 = a
     *
     * 2:将 n 带入原公式 就可以得出如下表达式 (下面的 "^" 不是异或运算,表示乘方)
     *      a 表示和,即传入的次数
     *      i 表示通过for循环的索引值,表示数列的第一个元素)
     *      n 表示数列的最后一个值,通过运算 直接求出
     *
     *      用上述符号替代原公式,得到如下公式
     *      (i + n)(n - i + 1) / 2 = a
     *
     *      拆分之后,就变成了一个二次函数
     *      2 * a = n ^ 2 - n * i + n + n * i - i ^ 2 + i
     *      2 * a = n ^ 2 + n - i ^ 2 + i
     *      根据二次函数的求根公式求解 n 的值  (-b + sqrt(b ^ 2 -4ac)) / 2a 得出 n 的值
     *      n ^ 2 + n - i ^ 2 + i - 2 * a = 0
     *      b ^ 2 -4ac 的值如下
     *      1 - 4 (i - 2 * a - i ^ 2);
     *
     *      n 的两个解如下
     *      (-1 + Math.sqrt(1 - 4 (i - 2 * a - i * i))) / 2
     *      (-1 - Math.sqrt(1 - 4 (i - 2 * a - i * i))) / 2
     *
     *      判断以下得到的 n 是否为一个整数(得到的结果为一个double类型) 为整数则说明从当前位置(i)出发 有连续的整数 和为 a
     *
     */
    public static int get(int a) {


        // 记录返回结果
        int res = 0;
        for (int i = 0; i < a; i++) {

            // b1 即为 ”n“ 对应的索引下标,只不过使用double表示
            double b1 = (-1 + Math.sqrt(1 - 4 * (i - 2 * a - i * i))) / 2;
            // 因为这个解为负数,所以不考虑
            //double b2 = (-1 - Math.sqrt(1 - 4 * (i - 2 * a - i * i))) / 2;
            System.out.println(b1);

            // 判断解是否为一个整数
            if (b1 - (long) b1 == 0) {
                res++;
            }
        }

        return res;
    }
}

发表于 2020-04-20 19:08:23 回复(0)
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        //System.out.println(t + "=" + t);
        method(t);
    }

    public static void method(int t) {
        int count = 1;
        int start = 0;
        for (int i = 2; i * (i - 1) <= 2 * t; i++) {
            if ((2 * t - i * (i - 1)) % (2 * i) == 0) {
                start = (2 * t - i * (i - 1) )/ (2 * i);
                if (start > 0) {
                    StringBuilder sb = new StringBuilder(new String(t + "="));
                    for (int j = 0; j < i; j++) {
                        int num = start + j;
                        sb.append(num).append("+");
                    }
                    String s = sb.substring(0, sb.length() - 1);
                    //System.out.println(s);
                    count++;
                }
            }
        }
        //System.out.println("Result:" + count);
        System.out.println(count);
    }
}

发表于 2022-05-27 21:52:13 回复(0)
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int ans = getSum(n);
        System.out.println(ans);
    }
/*
i = 1时,n % 1 == 0,本身就是一个结果
i = 2时,因为是连续整数,所以有a + a + 1 = n  => 如果(n - 1) % a == 0 那么就存在这个结果a
*/
    public static int getSum(int n){
        if(n == 0) return 1; 
         int ans = 0,i = 1;
        while(n > 0){
            if(n % i == 0){ //如果n能整除i,说明存在结果
                ans ++;
            }i
            n -= i; //(这里就让n - i)
            i += 1; //(i递增)
        }
        return ans;
    }
}
发表于 2020-09-05 19:09:45 回复(0)
为啥我这个超时了 请各位大佬康康..

package com.question.bilibili;
//给定一个正整数N,试求有多少组连续正整数满足所有数字之和为N? (1 <= N <= 10 ^ 9)

import java.util.Scanner;

public class Solution4 {
    /**
     *
     * @param num 正整数N
     * @return 多少组连续数
     */

    public static int findContinuousSequencesCount(int num){
        if(num <= 1) return 1;
        //计数值
        int count = 0;
        int low = 1;
        int high = 2;
        //low 表示左边界
        //high 表示右边界
        while(high > low){
            //具体值
            int sum = (low + high) * (high - low + 1) / 2;
            if(sum == num){
                count++;
                //值偏大
                low++;
            }else if(sum > num){
                //调整左边界 让值变小
                low++;
            }
            //调整右边界 让值变大
            else high++;
        }
        //自己本身
        return ++count;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int num = scanner.nextInt();
        System.out.println(findContinuousSequencesCount(num));
        scanner.close();
    }
}


发表于 2020-07-28 17:37:17 回复(0)
import java.util.Scanner;

public class Main{

    public static void main(String[] args){
        Scanner s = new Scanner(System.in);
        int input = s.nextInt();

        System.out.println(getNum(input));
    }

    public static int getNum(int border){
 int n=0;
        if(border==0){
            n=1;
            return n;
        }
        for(int i=1;i<=border;i++){             int count=0;             for(int j=i;j<=border;j++){                 count+=j;                 if(count == border){                     n++;                     break;                 }else if(count>border){                     break;                 }             }         }         return n;     } }
这题有问题,非要给个0,导致0+1+2+3+4+5=15,1+2+3+4+5=15,这就是两次了,导致结果出错。咳,我这个超时了
编辑于 2020-07-15 16:28:42 回复(0)
class Solution {
public:
    /*
      直接求算法复杂度有点大 转为为o(logn) 求因子
      推导过程:
         (start + end)(end - start +1) = 2*N;
          设 start + end = i;
          上式变为:(start + end)(end - start) + (start + end) = 2*N => (end - start)*i +i = 2*N;
          由上面2个式子可以求出 end=(2*N/i+i-1)/2,start=end-2*N/i+1.
      代码按照上面的写行

    */
    int consecutiveNumbersSum(int N){
        int res = 1;//1*本身算一个
        //i 表示其中的一个因子 所以i开始从2取
        for(int i=2;i<=sqrt(2*N);i++){
            if(2*N % i == 0){//肯定能整除
               int end = (2*N/i +i -1)/2;
               int start =end - 2*N/i +1;
               if((start + end)*(end - start+1) == N*2){
                   res++;
               }
            }
        }
        return res;

    }
};

发表于 2020-06-22 18:34:02 回复(0)
#include<bits/stdc++.h>
using namespace std;
 
 
typedef long long ll;
int main()
{
  ll n;
  cin >> n;
  ll res = 0;
  if(n == 0)
  {
     cout<<1<<endl;
     return 0;
  }
  ll m = 2*sqrt(2*n);
  // k^2 + (2a-1)*k - 2*N = 0
  //k为期间长度,a为起始,枚举k
  for(ll k = 1 ;k<m;k++)
    {
      if( (2*n - k*k + k)%(2*k) == 0 && (2*n - k*k + k)/(2*k) > 0)
    {
      //cout<<k<<" "<<(2*n - k*k + k)/(2*k)<<endl;
      res++;
    }
    }
  cout<<res<<endl;
  return 0;
}


发表于 2020-03-13 15:41:33 回复(0)
#include<bits/stdc++.h>
using namespace std;
 
int main(){
    int num;
    while(cin>>num){
        int tmp_num=1;
        int left=1,right=1; // 区间明确定义
        int res=1;
         
        for(;left<=(num>>1) ;){
            if(tmp_num==num){
                res++;
                tmp_num-=left++;
                tmp_num+=++right;
            }
            else if(tmp_num<num){
                tmp_num+=++right;
            }
            else{
                tmp_num-=left++;
            }
        }
        cout<<res<<endl;
    }
}
使用双指针法。  O(N) 如果想更高效,可以考虑使用等差数列公式。
发表于 2020-03-08 17:46:16 回复(0)