projecteuler#3 Largest prime factor
阿新 • • 發佈:2018-12-14
* Prime.php
<?php /** https://projecteuler.net/problem=3 The prime factors of 13195 are 5, 7, 13 and 29. What is the largest prime factor of the number 600851475143 ? */ class Prime { /** @var int */ private $value; public function __construct(int $value) { $this->value = $value; } public function isPrime(int $num) : bool { if ($num===2||$num===3) {return true;} // for x >=1, 6x,6x+1,6x+2,6x+3,6x+4,6x+5 // 6x+2,6x+3,6x+4 => 2(3x+1),3(2x+1),2(3x+2) if ($num % 6 !== 1 && $num % 6 !== 5) {return false;} for ($i = 5; $i * $i <= $num; $i += 6) { if ($num % $i === 0 || $num % ($i+2) ===0) { return false; } } return true; } private static function modMul(int $a, int $b, int $mod) : int { $res = 0; while ($b > 0) { if ($b & 1) { $res = ($res + $a) % $mod; } $a = ($a << 1) % $mod; $b >>= 1; } return $res; } private static function modPow(int $a, int $n, int $mod) : int { $res = 1; while ($n) { if ($n & 1) { $res = self::modMul($res, $a, $mod); } $a = self::modMul($a, $a, $mod); $n >>= 1; } return $res; } public static function millerRobin(int $n, int $loop = 20) : bool { if ($n===2) {return true;} if ($n < 2 || !($n & 1)) return false; $m = $n - 1; $k = 0; while (!($m & 1)) { $k++; $m >>= 1; } // Miller-Rabin測試的迭代次數 $loop = 20 while ($loop-- > 0) { $a = rand(0, $n-2) + 1; $x = self::modPow($a, $m, $n); $y = 0; for ($j = 0; $j < $k; $j++) { $y = self::modMul($x, $x, $n); if ($y === 1 && $x != 1 && $x != $n-1) { return false; } $x = $y; } if ($y !== 1) { return false; } } return true; } public function getPrimeFactors() { $factors = []; if ($this->isPrime($this->value)) { return [ $this->value ]; } // echo $this->value.' is not a prime number'.PHP_EOL; $last = ceil($this->value/2); $v = $this->value; for ($cur = 2; $cur <= $last && $cur <= $v; ) { if ($v % $cur === 0) { if ($this->isPrime($cur)) { // echo $cur . PHP_EOL; array_push($factors, $cur); // echo implode(',', $factors) . PHP_EOL; } $v /= $cur; } else { $cur++; } } return $factors; } } // test: // $ time php Prime.php $prime = new Prime(600851475143); $a = $prime->getPrimeFactors(); // [71, 839, 1471, 6857] print_r($a); echo $a[count($a)-1].PHP_EOL; // 6857 // 0.042s
* test
$ time php Prime.php
Array
(
[0] => 71
[1] => 839
[2] => 1471
[3] => 6857
)
6857
real 0m0.039s
user 0m0.020s
sys 0m0.010s