0

我只是在想一个似乎并不难的问题,但是当我们考虑以最佳方式进行时,它就变成了一个很好的问题。问题是 - 我们得到了一个数字列表(数组)和一个数字 N。我们必须找到 N 的所有除数,它们不会除掉任何属于该列表的数字。我已经用蛮力和一点有效的方法(但不是最好的方法)解决了它。所以,我正在寻找一种可能是解决这类问题的最佳方法。一切都是整数(没有浮点数)。每一个想法都值得赞赏。

我的方法是首先找到数字 N 的所有除数(没有任何开销)。然后,我以相反的顺序(单独)对列表和除数进行排序。现在,对于每个除数 D,我检查它是否除以列表中的任何数字(从最高元素开始到 >= 除数 D 的元素)。如果它除法,那么 D 的所有除数也必须除法。然后我从除数列表中删除这些元素,这些元素也是 D 的除数(可以认为是删除交集)。因此,最终左除数数组是所需的数组(根据我的方法)。如果有人可以指出我的方法中的任何错误或效率低下,我们将不胜感激。列表中可以存在的最大值为 10^18。

到目前为止我在 PHP 中的尝试:

while($div=each($divisors))
{
$i=0;
$divisor=$div['key'];
//echo "divisor is $divisor\n";
while((int)$unfriendly[$i]>=$divisor)
{//echo "aya\n";
    if(!((int)bcmod($unfriendly[$i],$divisor)))
    {//echo "ayeea\n";
        $divisors_of_divisor=divisors_of_a_number($divisor);
        //print_r($divisors_of_divisor);
        //print_r($divisors);
        foreach($divisors_of_divisor as $d)
        unset($divisors[$d]);
        //print_r($divisors);
        break;
    }
    ++$i;
}
 }
echo sizeof($divisors);
function divisors_of_a_number($n)//returns all the divisors of a number in an unsorted array
{
$i=1;
$s=sqrt($n);
while($i<=$s)
{
if(!($n%$i))
{
    $a[]=$i;
    if($i!=$s)
    $a[]=$n/$i;
}
++$i;
}
return $a;
}
function divisors_of_a_number_as_keys_of_array($n)//returns all the divisors of a number in an unsorted array as keys
{
$i=1;
$s=sqrt($n);
while($i<=$s)
{
if(!($n%$i))
{
    $a[$i]=1;
    //if($i!=$s)
    $a[$n/$i]=1;
}
++$i;
}
return $a;
}
4

1 回答 1

0

一个明显的优化如下 - 做eratosthenes 筛以将所有数字分解为一个您知道的值,该值高于您给出的列表中的任何单个值。现在您可以从该列表中迭代给定数字的所有因子。

你接下来要做的是:对于列表中的每个数字及其每个素因数 p,你应该将 N 除以 p,直到它可以被它整除。在你这样做之后,你正在寻找的除数都是剩余数字的除数。

希望这可以帮助。

于 2012-04-08T07:43:24.357 回答