求和算法的力量

时间:2017-12-13 11:07:34

标签: java algorithm recursion dynamic-programming

有关于n次幂之和的算法问题here,我试图使用递归来解决问题,这在我在网上检查解决方案之前没有用,我得到了这个:

public class Main {

public static void main(String[] args){

    Scanner s = new Scanner(System.in);
    int x = s.nextInt(), n = s.nextInt();
    int end = (int)Math.pow(x, 1.0/n);
    System.out.print(sumOfPower(x, n, end));

}


static int sumOfPower(int number, int power, int end) {
    int[] temp = new int[number + 1];
    temp[0] = 1;
    for(int i = 1; i <= end; i++) {
        int value = (int)Math.pow(i, power);
        for(int j = number; j > value - 1; j--) {
            temp[j] += temp[j-value];
        }

    }
    return temp[number];
}

我尝试通过在每个循环中记录结果来研究代码,因此sumOfPower方法现在看起来像这样:

static int sumOfPower(int number, int power, int end) {
    int[] temp = new int[number + 1];
    temp[0] = 1;
    for(int i = 1; i <= end; i++) {
        int value = (int)Math.pow(i, power);
        for(int j = number; j > value - 1; j--) {
            System.out.println( "j:"+j+"\tj-value:"+(j-value)+ "\ttemp[j]:" + temp[j] + "\ttemp[j-value]:" + temp[j-value] );
            temp[j] += temp[j-value];
            System.out.println(i + ": " + Arrays.toString(temp));
        }

    }
    return temp[number];
}

我理解循环和动态编程逻辑在某种程度上如何使用我使用x=10n=2的日志。日志看起来像:

10
2
j:10    j-value:9   temp[j]:0   temp[j-value]:0
1: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
j:9 j-value:8   temp[j]:0   temp[j-value]:0
1: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
j:8 j-value:7   temp[j]:0   temp[j-value]:0
1: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
j:7 j-value:6   temp[j]:0   temp[j-value]:0
1: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
j:6 j-value:5   temp[j]:0   temp[j-value]:0
1: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
j:5 j-value:4   temp[j]:0   temp[j-value]:0
1: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
j:4 j-value:3   temp[j]:0   temp[j-value]:0
1: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
j:3 j-value:2   temp[j]:0   temp[j-value]:0
1: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
j:2 j-value:1   temp[j]:0   temp[j-value]:0
1: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
j:1 j-value:0   temp[j]:0   temp[j-value]:1
1: [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
j:10    j-value:6   temp[j]:0   temp[j-value]:0
2: [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
j:9 j-value:5   temp[j]:0   temp[j-value]:0
2: [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
j:8 j-value:4   temp[j]:0   temp[j-value]:0
2: [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
j:7 j-value:3   temp[j]:0   temp[j-value]:0
2: [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
j:6 j-value:2   temp[j]:0   temp[j-value]:0
2: [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
j:5 j-value:1   temp[j]:0   temp[j-value]:1
2: [1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0]
j:4 j-value:0   temp[j]:0   temp[j-value]:1
2: [1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0]
j:10    j-value:1   temp[j]:0   temp[j-value]:1
3: [1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1]
j:9 j-value:0   temp[j]:0   temp[j-value]:1
3: [1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1]

我目前需要了解的是这背后的数学逻辑,我怎么知道在循环之后temp['number']x的总路径可以表示为总和唯一自然数的nth幂。任何帮助都非常感谢。

2 个答案:

答案 0 :(得分:2)

让我们从问题的抽象模型开始,给出一个DAG directed acyclic graph,从一个节点到另一个节点的旅行方式有多少?

让我们调用函数回答这个问题是f(start, end)

我们可以很容易地看到

f(start, end) = sum f(x , end) with x are the neighbours of start

和基本情况f(end, end) = 1(有一种方法可以从头到尾移动,因为这个图没有循环)。并且,由于这是DAG,因此上述函数将收敛。

同样,您可以看到同一模型可以应用于此问题。

假设我们需要计算f(X, 0),其中X是初始值,我们可以看到,从值X,我们可以达到所有值X - yy是第N电源号码。

所以

f(X, 0) = sum f(X - y, 0) with y is all Nth power number less than or equal X

f(0,0) = 1

在您提供的代码中,temp正在存储来自f的{​​{1}}的答案。

那么,为什么这是DAG?因为Nth幂的值是正的,所以我们不能回到以前的状态。

答案 1 :(得分:1)

这对我来说是递归的。只需要小心限制(开始,结束和目标总和):

public class powerSum {
    static int solutions = 0;

    static void process(int currentSum, int targetSum, int currentNumber, int n) {
    if (currentSum == targetSum) {
        solutions++;
        return;
    }

    for (int i = currentNumber; currentSum + (int) Math.pow(i, n) <= targetSum; i++)
        process(currentSum + (int) Math.pow(i, n), targetSum, i + 1, n);
    }

    public static void main(String[] args) {
        process(0, 100, 1, 2);
        System.out.println(solutions);
    }

}

解决方案= 3