我使用Mathematica解决Problem 23 of Project Euler:
求出所有正整数的总和,这些正整数不能写成两个数字的总和。
回想一下,#
就是Total[Divisors[#]] - # > #
。这是我的代码:
list1 = Table[i, {i, 1, 28123}];
list2 = Select[list1, Total[Divisors[#]] - # > # && 2 * # < 28123 &];
list3 = {};
l = Length[list2];
For[i = 1, i <= l, i++,
For[j = i, j <= l, j++,
list3 = Append[list3, list2[[i]] + list2[[j]]]]];
Total[Complement[list1, list3]]
非常慢;嵌套的For
循环需要花费大量时间来评估。
我是否正确处理此问题?有没有办法让它更快?
编辑: 28123
背后的原因是任何大于它的数字都可以写成两个数字的总和。
答案 0 :(得分:4)
用这个替换你创建list3的循环。
list3 = (list2[[#]] + list2[[# ;; -1]]) & /@ Range[Length[list2]] // Flatten;
我的旧电脑时间为0.49秒
<强>更新强>
回答抱怨我的答案中构建的list3给出了错误的解决方案。
好。它使用原始代码提供与list3 build相同的内容。这种方法更快。如果原始方法中的构造是错误的,那么我真的无法做到这一点,因为问题是关于如何使它更快,而不是纠正算法本身的任何错误,我不熟悉。假设发布的算法是正确但缓慢的。
(*28123 replaced with smaller value to check, else will take forevever*)
(*for original algorithm to finish *)
n = 200;
list1 = Table[i, {i, 1, n}];
list2 = Select[list1, Total[Divisors[#]] - # > # && 2*# < n &];
list3 = {};
l = Length[list2];
For[i = 1, i <= l, i++,
For[j = i, j <= l, j++,
list3 = Append[list3, list2[[i]] + list2[[j]]]]];
mylist3 = (list2[[#]] + list2[[# ;; -1]]) & /@ Range[Length[list2]] //Flatten;
比较
list3 - mylist3
答案 1 :(得分:2)
( 28123替换为较小的值来检查,否则将采取预测)
除非你别无选择,否则我会避免使用Mathematica中的for循环。我使用上述解决方案杀死了内核,因为它似乎需要很长时间才能完成。
下面的解决方案在我的Macbook上大约需要6秒钟。您可以将其上限设置为20161,正如其他人在Euler论坛中指出的那样。
Total[Complement[Range[20161],
Plus @@ # & /@
Tuples[Select[Range[20161], ((DivisorSigma[1, #] - #) > #) &], 2]]]
<强>更新强>
阅读其他一些关于优化的线程,我发现替换
<Plus @@ # &
Total[#]&
与Total[Complement[Range[20161],
Total[#] & /@
Tuples[Select[Range[20161], ((DivisorSigma[1, #] - #) > #) &], 2]]]
相隔一秒。
此版本需要4.9秒
if(true){
document.getElementById("div1").style.visibility = "hidden";
}