Pollard-rho算法[因子分解算法]


試除法:最簡單的因數分解算法,從$ 2 $到$ \sqrt n $一個一個試。

試除法(改進):從$ 2 $到$ \sqrt n $挑素數一個一個試。

然而這樣復雜度是相當高的。

生日悖論:指如果一個房間里有23個或23個以上的人,那么至少有兩個人的生日相同的概率要大於50%。

我們在$ [2,n) $取一個數,該數是$ n $的因子的概率很小.

我們取$ k $ 個數$ x_1,x_2,x_3...x_k $,而取出的 $ k $ 個數中,$ \exists i,j : (x_i-x_j) | n $ 的概率隨着$ k $ 增大而增高。

我們有一個更好的辦法:

對選取的$ k $ 個數 $ x_1,x_2,x_3...x_k $,不再詢問是否存在$ (x_i-x_j) | n $,改為詢問 $ gcd(x_i-x_j,n)>1 $ 的情況。

所以,一個簡單的策略如下:

1.在區間$[2,n)$ 中隨即選取$ k $個數$ x_1,x_2,x_3...x_k $

2.判斷是否存在$ gcd(x_i-x_j,n)>1 $ , 若存在,$ gcd(x_i-x_j,n)>1 $ 是$ n $的一個因子。

我們大概需要選取$ n^{\frac{1}{4}}$個數,這可能存不下。

Pollard's Rho 算法 

為了解決數太多無法儲存的問題,Pollard's Rho 算法之將兩個數存在內存里,我們生成並檢查這兩個數,反復執行這個步驟並希望得到我們想要的數。

我們不斷使用一個函數來生成這個序列(有點像隨機數),並非所有函數都可以,但有一個神奇的函數可以$ f(x)=(x^2+a)mod n $; $ a $ 可以指定也可以隨機。

這個序列顯然是存在環的,如何檢測環出現呢?

方法一:floyd判環法

floyd判環法:假如兩個人$A、B$在環上走,如何知道已經走完一圈呢? 讓$B$以$A$兩倍的速度走,$B$第一次趕上$A$時,$B$至少走完一圈了

設定$ x=y=x0 $的初始值,進行迭代,每次:$ x=f(x), y=f(f(y)) $ 即:$ x=x_i,y=x_{2i} $

若$ gcd(x−y,n)=1 $,那么繼續枚舉下一對 $x,y$ 。

若$ gcd(x−y,n)=n $,更換隨機函數 f(x)f(x) ,重新進行算法。

否者我們就找到了一個n的非平凡因子 $ d=gcd(x-y,n) $

當 $x==y$時出現循環,此時$x-y=0$,$ gcd(x−y,n)=n $,即為2情況。

LL pollardRho(LL n, int a){
    LL x=2,y=2,d=1;
    while(d==1){
        x=(x*x+a)%n;
        y=(y*y+a)%n;y=(y*y+a)%n;
        d=gcd(abs(x-y),n);
    }
    if(d==n) return pollardRho(n,a+1);
    return d;
}

方法二:brent判環法

不同於floyd每次計算$x_i,x_{2i}$進行判斷,brent每次只計算$x_i$,當$k$是2的方冪時,$y=x_k$,每次計算$d=gcd(x_k−y,n)$

 

LL pollardRho(LL n, int a){
    LL x=2,y=2,d=1,k=0,i=1;
    while(d==1){
        ++k;
        x=(x*x+a)%n;
        d=gcd(abs(x-y),n);
        if(k==i){y=x;i<<=1;}
    }
    if(d==n)return pollardRho(n,a+1);
    return d;
}

 

 求全部因子(結合miller-rabin測試)

LL cnt,fact[100];
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
LL pollardRho(LL n, int a){
    LL x=rand()%n,y=x,d=1,k=0,i=1;
    while(d==1){
        ++k;
        x=ksc(x,x,n)+a;if(x>=n)x-=n;
        d=gcd(x>y?x-y:y-x,n);
        if(k==i){y=x;i<<=1;}
    }
    if(d==n)return pollardRho(n,a+1);
    return d;
}
void findfac(LL n){
    if(millerRabin(n)){fact[++cnt]=n;return;}
    LL p=pollardRho(n,rand()%(n-1)+1);
    findfac(p);
    findfac(n/p); 
}

例題:POJ1811

https://files-cdn.cnblogs.com/files/Doggu/Pollard-rho%E7%AE%97%E6%B3%95%E8%AF%A6%E8%A7%A3.pdf

https://blog.csdn.net/qq_39972971/article/details/82346390

https://www.cnblogs.com/book-book/p/6349362.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM