将整数表示为连续正整数的总和

时间:2017-06-10 08:20:44

标签: java math

我正在编写用于计算整数可以表示为连续整数之和的方式的代码。例如

15 =(7 + 8),(1 + 2 + 3 + 4 + 5),(4 + 5 + 6)。因此,15的方式等于3。 现在输入大小可以是<= 10 ^ 12。我的程序工作正常,直到10 ^ 7(我想是的,但不确定,因为我没有在任何在线评判中检查它。随意检查代码)

但是只要我给它10 ^ 8或更高的整数作为输入。它抛出许多运行时异常(它不显示运行时错误)。提前谢谢。

import java.io.*;

//sum needs to contain atleast 2 elements
public class IntegerRepresentedAsSumOfConsecutivePositiveIntegers
{
    public static long count = 0;
    public static void main(String[] args) throws IOException
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        long num = Long.parseLong(br.readLine()); //Enter a number( <=10^12)
        driver(num);
        System.out.println("count = " + count);
    }

    public static void driver(long num)
    {
        long limit = num / 2;
        for(long i = 1 ; i <= limit ; i++)
        {
            func(i,num);
        }
    }

    public static void func(long i,long num)
    {
        if(i < num)
        {
            func(i + 1,num - i);
        }
        else if(i > num)
        {
            return;
        }
        else
        {
            count++;
        }
    }

}

4 个答案:

答案 0 :(得分:1)

使用一些数学:如果差异1的算术级数从a0开始并且包含n个项目,则其总和为

 S = (2 * a0 + (n-1))/2 * n = a0 * n + n * (n-1) / 2

请注意,第二个加数作为二次函数上升。因此,我们不会检查范围a0中的所有S/2,而是检查所有n是否更小范围

nmax = Ceil((-1 + Sqrt(1 + 8 * S)) / 2)

我使用了一些更高的近似值)。

只测试下一个表达式是否给出整数正结果

 a0 = (S - n * (n - 1) / 2) / n

答案 1 :(得分:0)

当你的输入大小与你的情况一样大时,递归函数并不合适。

java调用堆栈的最大深度约为8900次调用,有时仅在7700次调用堆栈溢出后才发生,因此它实际上取决于您的程序输入大小。

尝试使用此算法我认为它适用于您的问题:

它将在10^9之后正常工作,之后将花费更多的时间来完成程序的运行。

    long sum = 0;
    int count = 0;
    long size;
    Scanner in = new Scanner(System.in);
    System.out.print("Enter a number <=10^12: ");
    long n = in.nextLong();
    if(n % 2 != 0){
        size = n / 2 + 1;
    }
    else{
        size = n / 2;
    }
    for(int i = 1; i <= size; i++){           
       for(int j = i; j <= size; j++){
            sum = sum + j;
            if(sum == n){
                sum = 0;
                count++;
                break;
            }
            else if(sum > n){
                 sum = 0;
                 break;
            }
        }
    }
    System.out.println(count);

<强>输出

Enter a number <=10^12: 15
3

Enter a number <=10^12: 1000000000
9
BUILD SUCCESSFUL (total time: 10 seconds)

答案 2 :(得分:0)

正如@MBo所指出的,如果一个S号码可以划分为n个连续的部分,则S - T(n)必须可以被n整除,其中T(n)是第n triangular number个,因此您可以在O(sqrt(S))时间内计算分区数。

// number of integer partitions into (at least 2) consecutive parts
static int numberOfTrapezoidalPartitions(final long sum) {
    assert sum > 0: sum;

    int n = 2;
    int numberOfPartitions = 0;
    long triangularNumber = n * (n + 1) / 2;

    while (sum - triangularNumber >= 0) {
        long difference = sum - triangularNumber;

        if (difference == 0 || difference % n == 0)
            numberOfPartitions++;

        n++;
        triangularNumber += n;
    }

    return numberOfPartitions;
}

更多的数学会产生更简单的方法。 Wikipedia说:

  

正数的礼貌被定义为可以表示为连续整数之和的方式的数量。对于每个x,x的礼貌等于x的奇数除数大于1。

另见:OEIS A069283

因此,一个有很多优化空间的简单解决方案是:

// number of odd divisors greater than one
static int politeness(long x) {
    assert x > 0: x;

    int p = 0;

    for (int d = 3; d <= x; d += 2)
        if (x % d == 0)
            p++;

    return p;
}

答案 3 :(得分:0)

有一个非常好的证据可以通过求解唯一的奇数因子(Reference)来确定答案。基本上,对于目标值的每个奇数因子,存在该因子的奇数系列数乘以其平均值以产生目标值,或者存在等于该因子的奇数平均值,其可以乘以偶数大小的两倍系列达到目标值。

public static int countUniqueOddFactors(long n) {
    if (n==1) return 1;
    Map<Long, Integer> countFactors=new HashMap<>();
    while ((n&1)==0) n>>>=1; // Eliminate even factors
    long divisor=3;
    long max=(long) Math.sqrt(n);
    while (divisor <= max) {
        if (n % divisor==0) {
            if (countFactors.containsKey(divisor)) {
                countFactors.put(divisor, countFactors.get(divisor)+1);
            } else {
                countFactors.put(divisor, 1);
            }
            n /= divisor;
        } else {
            divisor+=2;
        }
    }
    int factors=1;
    for (Integer factorCt : countFactors.values()) {
        factors*=(factorCt+1);
    }
    return factors;
}