不重复 - optimal algorithm for finding unique divisors
我遇到了这个问题。我无法找到最佳算法。
问题是:
给定自然数的列表L
(数字可能非常大)和数字N
,确定N
的除数的最佳算法是什么不分割列表L
中的任何数字。列表中的数字可以是重复的,即一个数字可以出现不止一次。
观察:
d
的某些除数N
的除数也是N
的除数。
我的方法是:
N
。d
的foreach divisor N
,我检查它是否划分列表中的任何元素。(当你来检查列表中小于d
的元素时停止,因为列表已排序)d
除以列表L
中的某个数字,那么我不会检查d
的任何除数,也就是说,我跳过此检查。但是这个算法并不是这个问题的最佳选择。
有关更好算法的想法吗?
答案 0 :(得分:0)
您需要了解的是: co-primes (或相对素数)
在数论中,数学的一个分支,两个整数a和b 据说是互质(也拼写共同素数)或相对素数 只有正整数才能将它们均分为1。
所以要“转码”你的问题:
您基本上想要从N
列表中找到L
的副本数量。
当a
和b
是共同素数时?
如果两个数字相对素数则为最大公约数(GCD) 是1
PHP中的示例代码(对于GCD):
<?php
$gcd = gmp_gcd("12", "21");
echo gmp_strval($gcd) . "\n";
?>
简单地说:
$count = 0
e
中的Foreach元素L
:计算GCD(e,N)
N
和e
没有公约除数)。算了一下。 $count++
这就是它的全部内容。
答案 1 :(得分:0)
首先,分解n并以下列方式表示:p1:k1,p2:k2,...,pm:km,使得p1,p2,...都是素数,n = p1 ^ k1 * p2 ^ k2 ....
现在,迭代r1,r2,r3,...,rm使得r1&lt; = k1,r2&lt; = k2,...,rm&lt; = km并检查p1 ^ r1 * p2 ^ r2 .. 。* pm ^ rm除以L中的任何数字。如果不将计数增加1。
优化:为r1选择一个值。看看p1 ^ r1是否除以L中的任何数字。如果是,则为r2选择一个数字,依此类推。如果p1 ^ r1没有除以L中的任何数字,则将计数增加(k2 + 1)(k3 + 1) .. *(km + 1)。
示例N = 72,L = [4,5,9,12,15,20]: 将N写为原始乘积:2:3,3:2(2 ^ 3 * 3 * 2 = 72)。
p1=2, p2=3, k1=3, k2=2
count=0
r1=0:
r2=0:
Divides 4
r1=0:
r2=1:
Divides 9
r1=0:
r2=2:
Divides 9
r1=1:
r2=0:
Divides 4
r1=1:
r2=1:
Divides 12
r1=1:
r2=2:
L not divisible by 18. Count+=1 = 1
r1=2:
r2=0:
Divides 4
r1=2:
r2=1:
Divides 12
r1=2:
r2=2:
L not divisible by 36. Count+=1 = 2
r1=3:
r2=0:
L not divisible by 8. Count+=(k2+1) +=(2+1) = 5
答案 2 :(得分:0)
<?php
class Divisors {
public $factor = array();
public function __construct($num) {
$this->num = $num;
}
// count number of divisors of a number
public function countDivisors() {
if ($this->num == 1) return 1;
$this->_primefactors();
$array_primes = array_count_values($this->factor);
$divisors = 1;
foreach($array_primes as $power) {
$divisors *= ++$power;
}
return $divisors;
}
// prime factors decomposer
private function _primefactors() {
$this->factor = array();
$run = true;
while($run && @$this->factor[0] != $this->num) {
$run = $this->_getFactors();
}
}
// get all factors of the number
private function _getFactors() {
if($this->num == 1) {
return ;
}
$root = ceil(sqrt($this->num)) + 1;
$i = 2;
while($i <= $root) {
if($this->num % $i == 0) {
$this->factor[] = $i;
$this->num = $this->num / $i;
return true;
}
$i++;
}
$this->factor[] = $this->num;
return false;
}
} // our class ends here
$example = new Divisors(4567893421);
print $example->countDivisors();
?>