對Pollard's Rho演算法的理解
之前曾經碰到過要用到Pollard's Rho演算法的題目,不過當時沒有學這個演算法,只是備忘了一下,這兩天沒事幹把這個演算法學了。wiki上說這個演算法是一個通用的因數分解演算法,對於分解因子較小的組合數特別有用。
對於一個正整數n,在一般情況下,我們主要使用的是列舉1到n^(1/2)來求n的因子,所以演算法複雜度是O(n^(1/2))。但是實際上有更好的辦法,那就是Pollard's Rho演算法,這個演算法是一個隨機化的演算法,簡單的說不是完全靠譜,一般我們認為它的平均演算法複雜度是O(n^(1/4)),在64位範圍內都是很開心的。
這個演算法應用了一個非常神奇的思想——Birthday Trick。對於一個特定的目標值Aim,簡單的一次隨機企圖命中它的概率是1/n,但是隨機抽取k個值,這k個值中某兩個值的差值命中Aim的概率卻在k約為n^(1/2)時達到1/2。如果我們視n的因子為Aim(如果有的話),便可以用這個方法找到它了。
實際上上述演算法的複雜度是O(n),因為有k=n^(1/2)。又總共要比較k*k/2次。於是要優化。這裡一個重要的思路是對於一個合數n,設p和q是它的兩個因子,那麼n與p的倍數和q的倍數有最大公約數大於1(為p或q)。現在我們只要要求k個隨機值中某兩個數的差值是p或q的倍數就行了。然後就有k的取值下降到n^(1/4),具體怎麼算出來的我看不懂,就不深究了。
第二個重要優化是如何儲存k個數,實際上沒有必要儲存下來,因為它們是隨機數,我們只要用一個隨機函式不斷生成它們就好了,這裡一般用f(x) = (x * x + a) mod N來生成偽隨機數。注意到這裡我們放棄了兩兩比較k個數,只是比較k個數中相鄰的兩個,這樣也可以?我不知道。
在下來的一個問題是f的生成序列有可能是一個環,這就要求我們再加一個floyd的演算法來判環。
這樣就有一個可以在O(n^(1/4))時間內有1/2概率找出n的因子的演算法了。