有一類問題,要求咱們將一個正整數x,分解爲兩個非平凡因子(平凡因子爲1與x)的乘積x=ab。html
顯然咱們須要先檢測x是否爲素數(若是是素數將無解),可使用Miller-Rabin算法來進行測試。算法
Pollard Rho是一個很是玄學的方式,用於在O(n^1/4)的指望時間複雜度內計算合數n的某個非平凡因子。事實上算法導論給出的是O(√p),p是n的某個最小因子,知足p與n/p互質。可是這些都是指望,未必符合實際。但事實上Pollard Rho算法在實際環境中運行的至關不錯。dom
Pollard Rho利用僞隨機數生成公式來提供待測因子,其公式爲xi=xi-1^2+c(mod n),其中c是開始時確認的隨機常數。咱們只要給出x1,利用這個公式能夠生成一系列數值。因爲每一個數徹底依賴於前一個數,所以數值的分佈中一定含環,咱們設t爲環的路口,u爲環的周長,那麼有xt+i=xt+u+i。而整個數值分佈就像一個ρ符號,所以該算法的後綴用Rho來表示。咱們將該公式得出的序列視做隨機序列。post
生日悖論中指出一個√d個學生的班級中,指望至少有一對人在同一天生日,其中d是一年中的日期,即365。一樣一個√d我的的班級中,至少有一對人在同一天生日的機率大於50%。咱們將n視做一年中的天數,而1~n-1中的每一個值都對應一年中的日期,將x1,x2,...視做學生,那麼序列中指望有兩個有兩我的相同,只須要序列的長度達到√n便可。所以咱們能夠認爲ρ符號的尾部與環的周長的指望均爲√n。測試
假設n=ab,其中a與b均不是n的平凡因子,咱們假設a<=b,可知a<=√n。咱們記yi=xi(mod a)。可知:url
$$ y_i=x_i\left(mod\ a\right)=\left(x_{i-1}^2+c\right)\left(mod\ n\right)\left(mod\ a\right)=\left(x_{i-1}^2+c\right)\left(mod\ a\right) $$ $$ =\left(\left(x_{i-1}\left(mod\ a\right)\right)^2+c\right)\left(mod\ a\right)\Rightarrow\left(y_{i-1}^2+c\right)\left(mod\ a\right)=y_i\left(mod\ a\right) $$spa
咱們依據a爲模數創建了新的一個ρ型軌跡,且a的ρ型軌跡的環必然僅出現n的ρ型軌跡的環上的數值(模a的結果)。由一樣的分析可得a的ρ型軌跡的環的尾部和環的長度的指望均爲n^(1/4)。對於a的ρ型軌跡的環上的任意一點k,假設其對應的是兩個不一樣的值xi與xj,即xi<>xj(mod n)但xi=xj(mod a)。此時能夠知(xi-xj)=rp(mod n),而gcd(xi-xj, n)的結果必然是n的一個非平凡因子(且能被a整除)。咱們能夠利用一個特定的變量p前後在迭代到x1,x2,x4,x8,...時記錄這些值,以後每次都校驗gcd(xi-p, n)是否既非1又非n,若是知足則找到n的非平凡因子,不然繼續迭代。以前說過a的ρ型軌跡的環的尾部和環的長度的指望均爲n^(1/4),所以當咱們p記錄xh時,其中xh落在a的ρ型軌跡的環上且h大於等於環的周長時,此時咱們會沿着a的ρ型軌跡的環進行周而復始的循環迭代,最終在修改p以前xi回到了xh的位置,此時藉助gcd(xi-p, n)咱們就找到了一個n的非平凡因子。h的指望應該爲O(n^(1/4)),所以時間複雜度的指望應該爲O(n^(1/4))。code
下面給出代碼:htm
pollard_rho(x) c = random() xi = random() i = 1 h = 1 xh = xi while(true) xi = (xi * xi + c) % n f = gcd(x, abs(xi - xh)) if(f != 1 && f != n) return f i = i + 1 if( i == h * 2) h = i xh = xi