【问题标题】:Power of sum algorithm求和算法的幂
【发布时间】:2018-05-27 06:07:52
【问题描述】:

有一个算法问题here 关于 n 次方的总和,我尝试使用递归解决问题,但在我在线检查解决方案之前不起作用,我得到了这个:

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幂的总和的可能方式的总数唯一的自然数。非常感谢任何帮助。

【问题讨论】:

    标签: java algorithm recursion dynamic-programming


    【解决方案1】:

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

    让回答这个问题的函数是f(start, end)

    我们很容易看到

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

    对于基本情况f(end, end) = 1(有一种从头到尾的方式,因为该图没有循环)。而且,由于这是一个有向无环图,所以上面的函数会收敛。

    同样,你可以看到同样的模型可以应用于这个问题。

    假设我们需要计算f(X, 0),其中X是初始值,我们可以看到,从值X,我们可以达到所有值X - y,其中y是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(0, 0) to f(value, 0)f 的答案。

    那么,为什么这是一个 DAG?因为 N 次方的值是正的,所以我们无法回到之前的状态。

    【讨论】:

      【解决方案2】:

      这适用于我的递归。只需注意限制(开始、结束和目标总和):

      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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-24
        • 2013-01-24
        • 2016-11-16
        • 2015-06-06
        • 2014-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多