我在Project Euler上花了很长时间研究问题#23。
以下程序给出的答案是 4190428 ,我无法弄清楚原因。
我认为某处可能存在一两个字符错误。
public long problem23() {
ArrayList<Integer> abundantNumbers = new ArrayList<Integer>();
int limit = 28123;
for(int i = 2; i < limit; i++) {
if(isAbundantNum(i)) {
abundantNumbers.add(i);
}
}
boolean [] abundantSum = new boolean [limit+1];
for(int a = 0; a < abundantNumbers.size(); a++) {
for(int b = 1; b < abundantNumbers.size(); b++) {
int temp = abundantNumbers.get(a) + abundantNumbers.get(b);
if(temp <= limit) {
abundantSum[temp] = true;
} else {
break;
}
}
}
long sum = 0;
for(int i = 1; i <= limit; i++) {
if(!abundantSum[i]) {
sum += i;
}
}
return sum;
}
public boolean isAbundantNum(int n) {
int factorSum = 1;
for(int i = 2; i < Math.sqrt(n); i++) {
if(n%i == 0) {
factorSum += i; factorSum += n/i;
}
}
if(factorSum > n) {
System.out.println(n);
return true;
}
return false;
}
修改:添加了isAbundantNum(int n)
方法。
答案 0 :(得分:2)
你有2个错误......
for(int b = 1; b < abundantNumbers.size(); b++) {
'b'应该从零开始而不是1
for(int i = 2; i < Math.sqrt(n); i++) {
if(n%i == 0) {
factorSum += i; factorSum += n/i;
}
}
这样的保理会给你重复(比如2 * 2 = 4,你得到两个)。
尝试类似:
for(int i = 2; i < n; i++) {
if(n%i == 0) {
factorSum += i;
}
}
答案 1 :(得分:2)
这是另一个实现:
import java.util.ArrayList;
import java.util.List;
public class P23 {
final static int MIN = 12;
final static int MAX = 28123;
static boolean numbers[] = new boolean[MAX+1];
static List<Integer> abundantNumbers = new ArrayList();
public static void main(String args[]) {
generateAbundants(MIN, MAX);
int size = abundantNumbers.size();
for (int i = 0; i < size; i++) {
for (int j = i; j < size; j++) {
int current = abundantNumbers.get(i) + abundantNumbers.get(j);
if (current <= MAX) {
numbers[current] = true;
} else {
break;
}
}
}
long sum = 0;
for (int i = 1 ; i <= MAX ; i++ ) {
if ( numbers[i] == false ) {
sum += i;
}
}
System.out.println(sum);
}
private static int sumOfProperDivisors(int x) {
int sum = 1;
int squareRoot = (int) Math.sqrt(x);
for (int i = 2; i <= squareRoot; i++) {
if (x % i == 0) {
sum += i;
sum += x / i;
}
}
// if x is a perfect square, it's square root was added twice
if (squareRoot * squareRoot == x) {
sum -= squareRoot;
}
return sum;
}
private static boolean isAbundant(int x) {
if (x < sumOfProperDivisors(x)) {
return true;
}
return false;
}
private static void generateAbundants(int min, int max) {
for (int i = min; i < max; i++) {
if (isAbundant(i)) {
abundantNumbers.add(i);
}
}
}
}
时间:455毫秒
<强>解释强>
j
的默认值为i
。您可以j = 0
(正如Ted Bigham所说 - 在这种情况下为b
),因为它会起作用,但它会考虑每两个数字(12 + 20 = 20 + 12)。从i
开始,效率更高。为什么从1
开始并不好?因为你可以解决方案:在我的例子中24 = 12 + 12。for
循环,您可以使用包含sqrt
的方法,因为它更有效(O(sqrt(n))而不是O(n)) ,但你必须调整它。在我的示例中,您可以看到我有<= squareRoot
,因为如果我不使用=
,它会跳过一些值(例如:6是36的除数,但你不是将其包含在您的解决方案中)。因为我计算了6
两次,所以我删除了其中一个根。当然,泰德的方法很好,但有时候提高性能会更好,即使简单性受到影响。