我只是在考虑一个似乎并不难的问题,但是当我们考虑最佳地进行处理时,它就成了一个很好的问题。问题是- 我们得到了一个由数字组成的列表(数组)和一个数字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; }
下面是一个明显的优化方法- 筛选掉橡皮擦以将所有数字增加到您所知道的值高于给定列表中任何一个的值。现在,您可以遍历该列表中给定数字的所有因子。
接下来要做的是:对于列表中的每个数字及其每个素数p,都应将N除以p,直到将其整除。完成后,您要查找的除数就是剩余数的所有除数。
希望这可以帮助。