一个Project Euler Puzzler(特别是PHP)


A Project Euler Puzzler (specifically in PHP)

最近还有一个Project Euler的问题,但我认为这有点具体(我只对基于PHP的解决方案感兴趣),所以我还是在问。

问题5问你:"能被1到20的所有数字整除的最小数字是什么?"

现在,我已经解决了两次。一次效率很低,一次效率更高,但我离一个特别复杂的答案还很远(我的数学不是特别扎实,因此我的强力解决方案)。我可以看到我可以改进的几个方面,但我想知道你们中是否有人能证明这个问题的更有效的解决方案。

*剧透:这是我的不太理想(运行7秒),但仍然可以忍受的解决方案(不确定该怎么办双$…只是假装你只看到1…

    function euler5(){
        $x = 20;
        for ($y = 1; $y < 20; $y++) {
            if (!($x%$y)) {
            } else {  
                $x+=20;
                $y = 1;  
            }   
        }echo $x;
     };

为1到20之间的所有数字收集素数。计算每个素因子的最大指数,我们有16 = 2**49 = 3**2,以及5,7,11,13,17,19(每个只出现一次)。把这个数字相乘,你就有答案了。

在php中,它看起来像这样:

<?php
function gcd($a,$b) {
    while($a>0 && $b>0) {
        if($a>$b) $a=$a-$b; else $b=$b-$a;        
    }
    if($a==0) return $b;
    return $a;
}
function euler5($i=20) {
    $euler=$x=1;
    while($x++<$i) {
        $euler*=$x/gcd($euler,$x);
    }
    return $euler;
}
?>

它的速度至少是你发布的速度的两倍。

Chris Jester Young是对的。

一般来说,如果你想要一个最小的数,它可以被从1到N的所有数整除,你会想要找到从2到N的全部素数,对于每一个素数,都要找到它除以该范围内任何数的最大次数。这可以通过找到不大于N的素数的最大幂来计算。

在20的情况下,正如克里斯所指出的,2^4是不大于20的2的最大幂,3^2是不大于20%的3的最大幂。对于所有其他素数,只有一次幂不大于20。

您可以删除一些被除的数字,例如1是不必要的,所有自然数都可以被1整除。您也不需要2,因此,所有数字都可以被2的倍数整除(4、8、16等)也可以被2整除。因此,相关的数字将是11、12、13、14、15、16、17、18和19。

因此:

<?
function eulerPuzzle()
{
  $integers = array( 11,12,13,14,15,16,17,18,19 );
  for ($n = 20; 1; $n += 20 ) {
    foreach ($integers as $int) { 
      if ( $n % $int ) { 
    break; 
      }
      if ( $int == 19 ) { 
    die ("Result:" . $n); 
      }
    }
  }
}
eulerPuzzle();
?>
<?php
$i=20;
while ($i+=20) {
    for ($j=19;$j!==10;--$j){
        if ($i%$j) continue 2;
    }
    die ("result: $i'n");
}

是迄今为止最快、最短的php解决方案。在我的电脑上比Czimi快1.4倍。但是看看python的解决方案,这是一个不错的算法。

有些人真的想得太多了。。。

Ruby中:

puts 5*7*9*11*13*16*17*19

@做简单数学的人;我不确定这是否是练习的目标。你要学习新的语言和新的表演方式。仅仅用计算器计算是不对的。

我知道这是一个旧帖子,但它仍然出现在谷歌结果中:)

用代码(就是PHP)做这件事,我发现这是最快的解决方案:

function eulerPuzzle() {
    $integers = array (11, 12, 13, 14, 15, 16, 17, 18, 19 );
    for($n = 2520; 1; $n += 2520) {
        foreach ( $integers as $int ) {
            if ($n % $int) {
                break;
            }
            if ($int == 19) {
                die ( "Result:" . $n );
            }
        }
    }
}
eulerPuzzle ();

是的,这是CMS的修改作品。它更快的主要原因是,当你阅读问题时,他们已经指出前10个整数的最低可能数是2520。因此,您可以只增加2520,而不是20。导致循环次数减少126次

我知道你说的是PHP,但这是我用Python写的草稿。

#!/usr/bin/env python
from operator import mul
def factor(n):
    factors = {}
    i = 2
    while i < n and n != 1:
        while n % i == 0:
            try:
                factors[i] += 1
            except KeyError:
                factors[i] = 1
            n = n / i
        i += 1
    if n != 1:
        factors[n] = 1
    return factors
base = {}
for i in range(2, 2000):
    for f, n in factor(i).items():
        try:
            base[f] = max(base[f], n)
        except KeyError:
            base[f] = n
print reduce(mul, [f**n for f, n in base.items()], 1)

它没有我能做的那么优雅,但它计算出了从2到2000的最小公倍数,在.15秒内。如果你的迭代解决方案每秒能处理10亿个候选者,那么它将需要10^849年才能完成。

换句话说,不要麻烦优化错误的算法。