1
#include <iostream>
#include <cstdlib>
typedef  unsigned long long int ULL;
ULL gcd(ULL a, ULL b)
{
   for(; b >0 ;)
   {
       ULL rem = a % b;
       a = b;
       b = rem;
   }
   return a;
}
void pollard_rho(ULL n)
{
   ULL i = 0,y,k,d;
   ULL *x = new ULL[2*n];
   x[0] = rand() % n;
   y = x[0];
   k = 2;
   while(1){
       i = i+1;
       std::cout << x[i-1];
       x[i] = (x[i-1]*x[i-1]-1)%n;
       d = gcd(abs(y - x[i]),n);
       if(d!= 1 && d!=n)
          std::cout <<d<<std::endl;
       if(i+1==k){
         y = x[i];
         k = 2*k;
       }
   }
}

int main()
{
   srand(time(NULL));
   pollard_rho(10);

}

此实现源自 CLRS 第 2 版(第 894 页)。while(1)在我看来很可疑。while 循环的终止条件应该是什么?

我试过k<=n了,但这似乎不起作用。我得到分段错误。代码中的缺陷是什么以及如何纠正它?

4

3 回答 3

1

为什么要存储所有这些中间值?你真的不需要把 x 和 y 放在一个数组中。只需使用您不断重复使用的 2 个变量,x以及y.

另外,替换while(1)while(d == 1)并在之前切断循环

 if(d!= 1 && d!=n)
      std::cout <<d<<std::endl;
   if(i+1==k){
     y = x[i];
     k = 2*k;

所以你的循环应该变成

while(d == 1)
{
    x = (x*x - 1) % n;
    y = (y*y - 1) % n;
    y = (y*y - 1) % n;
    d = abs(gcd(y-x,n))%n;
}
if(d!=n)
  std::cout <<d<<std::endl;
else
  std::cout<<"Can't find result with this function \n";

如果您将循环内使用的函数作为参数传递给 ,则额外加分pollard,这样如果它无法找到一个函数的结果,它会尝试另一个函数。

于 2011-05-18T06:32:14.427 回答
1

我只有 CLRS 的第 1 版,但假设它与第 2 版差别不大,终止条件的答案在下一页:

这个寻找因子的过程起初可能看起来有些神秘。但是请注意,POLLARD-RHO 永远不会打印错误的答案。它打印的任何数字都是n的重要除数。不过,POLLARD-RHO 可能根本不打印任何东西。不能保证它会产生任何结果。然而,我们将看到,有充分的理由期望 POLLARD-RHO在while循环的大约 sqrt( p ) 次迭代之后打印n的p因子。因此,如果n是复合的,我们可以期望这个过程在大约n 1/4更新后发现足够的除数来完全分解n,因为每个素因数n中的p(可能最大的除外)小于 sqrt( n )。

因此,从技术上讲,CLRS 中的演示文稿没有终止条件(这可能是他们称之为“启发式”和“程序”而不是“算法”的原因),并且不能保证它会实际产生任何东西有用。在实践中,您可能希望根据预期的n 1/4更新设置一些迭代界限。

于 2011-05-18T14:47:42.643 回答
0

尝试用while(1) { i = i + 1;这个替换:

for (i = 1; i < 2*n; ++i) {
于 2011-05-18T06:01:19.027 回答