有没有办法将任何数字表示为4个方格的总和?

时间:2011-08-18 05:45:55

标签: java

有没有办法将任何数字表示为4个方格的总和。

例如,29可以表示为5 ^ 2 + 2 ^ 2 + 0 ^ 2 + 0 ^ 2

我尝试了以下代码,但是一些数字给出了15个例子,例如23 ^ 4 + 2 ^ 2 + 1 ^ 2 + 1 ^ 2 + 1 ^ 2

我尝试的代码是:

 x=0;
 while(num!=0){
          x=(int)Math.floor(Math.sqrt(num));
         num=num-(x*x);        
}

6 个答案:

答案 0 :(得分:8)

与波希米亚人所说的不同,我用以下四个方面解决了23个问题:

23 = 3^2 + 3^2 + 2^2 + 1^2

29如下:

29 = 4^2 + 3^2 + 2^2 + 0^2

我的逻辑将从:

开始
  1. 从数字的平方根开始 - 1.例如SQRT(29) = 5 - 1 = 4;这是我们的第一个任期。
  2. 从点1获取值,将其平方并再次向其添加第1点的平方值,并查看它是否大于N.如果是,则将第二个和项递减1并将平方值加到来自1)的价值。
  3. 如果先前的平方值项总和小于N,则找到下一个值项并重复2),直到您有所有4个项加起来为N.
  4. 注意:这是针对您的简单案例。对于复杂的情况,例如323,这可能不起作用。

    323 = 17^2 + 4^2 + 3^2 + 3^2
    

    请记住,当您找到x项时,该项的值小于或等于 x-1(上一个)项的值。

答案 1 :(得分:3)

以下是您的算法代码

这将为您提供所有可能的组合......

int n, t1, t2, t;
        n = 29;//Your number

        for (int i = (int) Math.sqrt(n / 4); i * i <= n; i++) {
            t1 = n - i * i;
            for (int j = (int) Math.sqrt(t1 / 3); j <= i && j * j <= t1; j++) {
                t2 = t1 - j * j;
                for (int k = (int) Math.sqrt(t2 / 2); k <= j && k * k <= t2; k++) {
                    t = (int) Math.sqrt(t2 - k * k);
                    if (t <= k && t * t == t2 - k * k) {
                        System.out.println("(" + i + "^2) + (" + j + "^2) + ("+ k + "^2) + ("+ t +"^2)");
                    }
                }
            }
        }

答案 2 :(得分:3)

在最初回答错误之后,我想我会对其进行编码:此解决方案有效。

我已经测试了这段代码并且它在O(log n)时间内执行,直到非常大的数字(在旧的macbook pro上解决n = Long.MAX_VALUE在75 ms内)

public static void main(String[] args) {
    long number = 827347833323423451L;
    LinkedList<Long> solution = new LinkedList<Long>();
    if (fourSquares(number, solution))
        System.out.println(number + " = sum of squares of: " + solution);
    else
        System.out.println(number + " could not be solved"); // never happens
}

public static boolean fourSquares(long number, LinkedList<Long> solution) {
    if (number == 0) {
        for (long i = solution.size(); i < 4; i++)
            solution.add(0L);
        return true;
    }

    if (solution.size() == 4)
        return false;

    for (long i = (long) Math.sqrt(number); i > 0; i--) {
        solution.add(i);
        if (fourSquares(number - i * i, solution))
            return true;
        solution.removeLast();
    }

    return false;
}

输出:

9223372036854775807 = sum of squares of: [3037000499, 76994, 671, 23]

答案 3 :(得分:2)

所以,我无法理解这一点,并使用动态编程,特别是memoization在Java中解决它。

以下是相关位:

private final Map<Integer, int[]> memo = new HashMap<Integer, int[]>();

/**
 * @param n
 *        the number
 * @return int[]
 */
public int[] solveFor(final int n) {
    if (memo.containsKey(n)) {
        return memo.get(n);
    }
    final int[] a = new int[4];
    a[0] = (int) Math.floor(Math.sqrt(n));
    if (sumOfSquares(a) < n) {
        int[] b = solveFor(n - a[0] * a[0]);
        while (a[0] > 0 && b[3] > 0) {
            // won't fit
            a[0]--;
            b = solveFor(n - a[0] * a[0]);
        }
        System.arraycopy(b, 0, a, 1, 3);
    }
    memo.put(n, a);
    return a;
}

在这个低至2.4GHz的i5上,它可以在不到3秒的时间内计算出从0到2,000,000的所有分解。

当然,明显的缺点是,如果要求计算所有整数到大数字,它会很快耗尽内存。但是,如果它被要求解决,比如4200万,那么它可以在几毫秒内生成正确的答案。

我也很确定它仍然可以被改进/优化 - 特别是如果它发现剩余的解决方案太长而无法适应剩余的空间,那么只是递减第一项的部分,但我会将其保留为为有更好的数学技能和更多空闲时间的人练习。 :)

答案 4 :(得分:1)

这很难实现,因为如果一个素数介于两者之间,你永远不能将它打破为1的平方根;例如,

拿11,

3 ^ 2 ---现在2仍然是没有平方根,小于此数字是“1”,1 ^(n)总是1 ..所以总是有一个提醒..

所以可能你需要遵循某种算法,因为其他答案建议......

答案 5 :(得分:-1)

代码没有问题。

23只需要5个术语来解决。

如果达到限制4,请尝试计算术语数并终止循环。

EDITED:

查看我的其他(更好)答案