【问题标题】:Calculating prime factors for Project Euler计算 Project Euler 的主要因子
【发布时间】:2012-03-11 08:48:07
【问题描述】:

我需要找到一个大数的最大素因数:最多 12 位 (xxx,xxx,xxx,xxx)。我已经解决了这个问题,代码适用于小数字(最多 6 个位置);但是,代码运行速度不够快,不会在我的服务器上触发超过 1000 亿的超时。

我找到了解决办法,谢谢大家。

代码:

<?php   
    set_time_limit(300);

    function is_prime($number) {
        $sqrtn = intval(sqrt($number));
        //won't work for 0-2
            for($i=3; $i<=$sqrtn; $i+=2) {
                if($number%$i == 0) {
                    return false;
                }
            }
        return true;
    }   

    $initial = 600851475143;
    $prime_factors = array();

    for($i=3; $i<=9999; $i++) {
        $remainder = fmod($initial, $i);
        if($remainder == 0) {
            if(is_prime($i)) {
                $prime_factors[] = $i;
            }
        }
    }

    //print_r($prime_factors);
    echo "\n\n";
    echo "<b>Answer: </b>". max($prime_factors);    
?>

本例测试号为600851475143。

【问题讨论】:

  • 如果你需要 greatest - 你可能从$sqrti 遍历到 2,而不是相反
  • 确定for($i=$sqrti; $i&gt;=2; $i--) {
  • 这看起来像欧拉项目,精神是不找解决方案,直到你自己解决。或者至少让人们知道它来自 PE。
  • @zerkms 您不需要遍历数十亿个项目。对于我的回答中的建议,OP 的最坏情况是number_of_divisors * sqrt(n),这是几百万步。如果你做对了并得到了质因数分解,那是 O(sqrt(n)) 最坏的情况。将素数筛选到平方根并仅使用这些素数比简单的试除法需要更多时间(更不用说空间了)。
  • 次要优化细节:在if ((is_prime($factor)) &amp;&amp; (is_factor($number, $factor))) { 行中交换is_prime()is_factor()(先做便宜的调用,希望避免昂贵的调用)

标签: php performance algorithm


【解决方案1】:

这是一个非常简单快速的解决方案。

LPF(n)
{
    for (i = 2; i <= sqrt(n); i++)
    {
        while (n > i && n % i == 0) n /= i;
    }

    return n;
}

【讨论】:

    【解决方案2】:

    您的代码将找不到任何大于sqrt(n) 的素数。要纠正这个问题,您还必须针对找到的每个因子(不仅是素因子)测试商 $number / $i

    你的is_factor 函数

    function is_factor($number, $factor) {
        $half = $number/2;
        for($y=1; $y<=$half; $y++) {
                if(fmod($number, $factor) == 0) {
                return true;
            }
        }
    }
    

    没有意义。 $y 和循环是什么?如果$factor 不是$number 的除数,那将执行$number/2 完全没有意义的除法。修复此问题后,对 is_prime_factor 中的测试重新排序将提供良好的加速,因为只需对 $number 的少数除数执行代价高昂的素性测试。

    【讨论】:

    • 感谢您的回答...虽然它不是我使用的,但它帮助我解决了问题。 :)
    猜你喜欢
    • 1970-01-01
    • 2012-07-20
    • 2015-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-19
    • 1970-01-01
    相关资源
    最近更新 更多