项目欧拉#23 Mathematica

时间:2012-12-18 00:21:27

标签: wolfram-mathematica

我使用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背后的原因是任何大于它的数字都可以写成两个数字的总和。

2 个答案:

答案 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

Mathematica graphics

答案 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";
    }