1. 程式人生 > >【快速因數分解】Pollard's Rho 演算法

【快速因數分解】Pollard's Rho 演算法

演算法目的

給一個數n,快速提取n的一個因數。

演算法根據:生日悖論

講生日悖論之前,先看一個東西。
給出[1..1000]的數,從中任意選出一個數為k的概率是11000
但是假如選出兩個數p,q要求他們的差值為k,就是|p-q|=k的概率大概是1500,因為要去絕對值。
繼續向下,選出l個數,使他們之間有兩個數的差值為k,那麼概率會隨l的變大而變大,最終會趨近於1。
接下來是生日悖論:
我們隨機選擇一名學生,他的生日為 4 月 1 日的概率為 [1..365]
這相當於我們在[1..365]中隨機選取一個數,該數為 90 的概率是多少?
那麼我們又回到了上面那個問題。
我們隨機選取 k(k≥ 2)個人 ,他們的生日相同的概率是多少(就是差值為0)?
我們可以看到,k = 10 的時候大概有 11%的可能性存在兩個人生日相同的情況,
而 k = 23 時,可能性提高至50%,假如一個班級總共有57個人,而l=57時的可能性已達到99%,幾乎可以肯定地說,一個班級裡必定有兩個同學的出生日期是相同的,而這麼多年的求學生涯過來了,這個概率“似乎”是不正確的,這便是悖論了。

Pollard’s Rho 演算法

那麼竟然有了這個玄學的悖論,我們就可以隨機的快速分解n了,2333。
有一個隨機函式f(x)=(x*x+d)%n,d=rand()。然後每次隨機出來的數和上一次隨機出來的數的差值與n去一個最大公因數,然後判斷一下就好了。
但是假如一直找不到符合的數然後死迴圈了怎麼辦。
我們可以用Floyd發明的機智判環演算法,因為我每次a=f(a),再找一個b=f(f(b)),如果有一個時刻a=b那麼就退出迴圈,因為b是以兩倍的速度走得,當b追上了a,那麼b至少已經走完一圈了。
複雜度O(n14),看上去O(玄學)。

Code

隨機函式f

ll f(ll x
){ int u=rand(); return (cheng(x,x,n)+po)%n; }

Pollard’s Rho 演算法

a=0;
    b=1;
    po=rand()%n+1;
    while(1){
        a=b=rand()%n+1;
        while(1){
            a=f(a);
            b=f(f(b));
            if(a==b)break;
            ll ui=abs(b-a);
            ll tt=gcd(ui,n);
            if
(tt==1||tt==n)continue; if(tt>1){ p=tt; break; } } po--; if(p)break; }