我正在研究一个问题,即将整数数组作为用户的输入。该程序计算数组元素的乘积。计算如下:
例如,让输入为56,61,2。然后程序首先执行56 * 61 = 3416
,然后modulo 3416 with 199 = 33
。现在取数组中的下一个元素,即2,然后乘以33 = 66.结果为3416 + 33 = 3482
。这是isotopes atom
的计算。
现在,如果我们可以重新排列数组的元素,即61,2,56;我们可以达到如下最大产品:
61 * 2 = 122
122 * 56 = 6832
6832 + 122 = 6954
我编写的程序明确地计算了输入数组的乘积但是现在我想按照上面提到的排序数组。我的计划如下:
import java.util.*;
public class codevita1 {
public static void main (String []args) {
int num = 0;
try {
num = Integer.parseInt (args[0]);
} catch (Exception e) {
System.err.println ("Arguments not enough");
}
int arr[] = new int[num];
for (int i = 1; i <= num; i++) {
arr[i-1] = Integer.parseInt(args[i]);
}
new codevita1().calcEnery (arr);
}
private int calcEnergy (int elements[]) {
int energy = 0;
int t = 1;
for (int i = 0; i < elements.length; i++) {
if (i == 0) {
energy = (elements[i] * elements[++i]);
} else {
energy += (t * elements[i]);
}
t = energy % 199;
}
return energy;
}
}
我已经搜索过动态编程和分治算法,但我无法理解哪种算法可以帮助我完成任务。请帮我解决一下我应该使用哪种算法以及如何使用算法?
答案 0 :(得分:1)
天真的方法是检查每个排列,并且需要O(n!)时间。
您也可能会注意到(a%199 * b)%199 =(a * b)%199 它允许我们检查在两个几乎相等的子集中分割数字集的每种方式。 当我们检查分裂的方法时,我们可以计算在第一子集的计算能量之后剩余的t作为第一子集%199中的所有数字的乘积,它将保持恒定,而不管子集中的元素的顺序。 然后我们可以递归计算两个子集的最优顺序。
如果子集的顺序很重要,可以使用C(n,n / 2)方法在两个子集中分割n个数。 C(n,n / 2)&lt; 2 ^ n因此总操作次数小于2 ^ n * 2 * 2 ^(n / 2)* 4 * 2 ^(n / 4)* 8 * 2 ^(n / 8)* ... * 2 ^(log(n)/ 2)* 2 ^(2)* 2 ^(log(n))* 2 ^ 1即~2 ^(2 * n + 2 * log(n))即O(2 ^ n)所以仍然很慢但比n好!
我怀疑在更多的子集(更准确地说是每个中的sqrt(n)子集sqrt(n)元素)中拆分可能要好得多,但是还没有计算出这种情况的复杂性。 / p>