项目Euler 214,我怎样才能提高效率?

时间:2009-04-20 09:12:13

标签: matlab

我越来越沉迷于项目欧拉问题。但是,因为有一周我被#214所困扰。

以下是问题的简短版本: PHI()是Euler的整数函数,即对于任何给定的整数n,PHI(n)= k <= n的数,gcd(k,n)= 1。

我们可以迭代PHI()来创建一个链。例如从18开始:

  

PHI(18)= 6 =&gt; PHI(6)= 2 =&gt; PHI(2)= 1。

从18开始,我们得到一条长度为4(18,6,2,1)

的链

问题是计算所有小于40e6的素数之和,它产生一个长度为25的链。

我构建了一个计算任何数字链长的函数,我测试了它的小值:它工作得很好而且速度很快。
所有素数的总和&lt; = 20,其产生长度为4:12的链 所有质数的总和&lt; = 1000,其产生长度为10:39383的链

不幸的是我的算法不能很好地扩展。当我将它应用于问题时,计算需要几个小时...所以我停止它,因为Project Euler问题必须在不到一分钟内解决。

我认为我的主要检测功能可能很慢所以我给程序提供了一个素数列表&lt; 40e6以避免素性测试...代码现在运行得快一点,但仍然没有办法在不到几个小时内得到一个解决方案(我不希望这样)。

那么我在这里缺少任何“魔术”吗?我真的不明白如何在这个上更有效率......

我不是要求解决方案,因为与优化战斗是Project Euler的所有乐趣。但是,任何可能让我走上正轨的小提示都会受到欢迎。

谢谢!


抱歉,评论的格式错误,我无法删除。所以这又是:

要计算totient函数,我使用以下内容: 对于给定的n,让我们调用它的因子列表 phi(n)= n * prod((p-1)/ p)

例如:2,3是18 =>的因子。 phi(18)= 18 * 1/2 * 2/3 = 6

所以这样我不计算任何gcd。给我这些因素的函数是用MATLAB构建的(是的,我忘了提到我在Matlab中编写代码)。也许我应该重写分解函数......

6 个答案:

答案 0 :(得分:3)

我会猜测耗时的部分是计算数字的总数。

一种想法可能是尝试以一种聪明的方式生成这些。考虑是否可以一次性计算所有这些,而不是一次计算一个数字...

另外,你如何计算totient函数?定义(整数k的数量,其中gcd(n,k)== 1)不是一种有用的方法。查一查,看看你是否能找到更合适的配方。

编辑: 是的,这就是我追求的表达方式。但是,遍历每个整数,将其分解,并计算总数太慢。寻找一种计算总体而无需进行任何分解的方法......

答案 1 :(得分:3)

尝试倒退...(从1,2等开始,按照自己的方式努力,而不是试图回到链接并链接到链中)

编辑:还要注意,totient(x)有一个particular structure,即totient(x)= x *(1-(1 / p))的乘积,其中p是除x的不同素因子

答案 2 :(得分:3)

提示

  1. 使用备忘录,不要多次计算phi(n)

  2. 在计算phi(N)时,尝试使用已计算的phi()的值作为较小的n。类似于phi(m*n) = phi(m) * phi(n) [mn应具备哪些属性?

  3. 当p是素数时,你知道phi(p)是什么吗?

答案 3 :(得分:1)

我还没有解决它,但我认为你的缓存方案可能正在走上正轨,你可能没有正确的缓存。希望对你来说没有太多或太模糊的“暗示”。

答案 4 :(得分:1)

嗯,我不熟悉它,你没有表现出你在做什么...但是有些想法:

  • 简化gcd;你不需要知道答案 - 只是是否有任何公共因子 - 因此将较小的数字(来自素数列表)分解并测试每个项与较大的数字

答案 5 :(得分:0)

有一点需要注意的是,一旦你达到6,例如,链的其余部分总是2,1。