筆記:A Quick Tutorial on Pollard's Rho Algorithm
筆記:A Quick Tutorial on Pollard's Rho Algorithm
Pollard's Rho是一種尋找整數真因子的概率化演算法,屬於蒙特卡羅方法的一個例項。
起步
尋找真因子的最簡單的方法是試除,簡單優化後有O(√n)
的複雜度(視整數長度為常數)。
試除法是逐個嘗試可能的選項。對其進行隨機化優化,可以從嘗試的方法入手。
我們有一個輸入n,簡單起見,我們設n是合數,並僅有兩個真因子p,q (p * q = n)
。
簡單的一步:我們直接在隨機一個小於n的數,並檢測它是否可以整除n,這個演算法是常數級的,不過命中的概率是2 / n
。
雖然我們有一個常數級的演算法,不過它的成功率與輸入成反比,不太可能通過重複來得到一個高效的演算法。
Birthday Trick
解決這個問題的方法用到了Birthday Trick。
設想從 1 ~ 1000 中選一個數,看它是否是常數 48,我們命中的概率是1 / 1000
。
如果我們一個選擇方法:從 1 ~ 1000 中選兩次,得到兩個數 i, j (i >= j)
,問i - j
是否等於 48,命中的概率是952 * 2 / (1000 * 1000)
,大概是1 / 500
,概率提高了。
試著將這個方法推廣:隨機選擇k個數,並在其中兩兩比較。
(原文中直接給出實際測試的效果:在k = 30
左右有一半的命中率。最後得出結論為對於n,在k = √n
處有一半的命中率。)
回到原題
現在要把Birthday Trick的方法應用到尋找真因子上來。
我們在起步時給出的概率化演算法其實可以這樣看:從 1 ~ n 中選出一個數並問它是否是 p 或 q。
所以直接推廣,選出√n個數並在之中兩兩比較,尋找到i - j
整除n(即i - j = p 或 q
)
可以問題沒有這麼簡單,現在我們要儲存√n個數,還要進行√n * √n
次比較,而且只有一半的概率找到真因子。
隨機函式
顯然,我們不能儲存√n個數,也不能進行n次比較。
如果我們只是在生成隨機數時,比較生成時間上相鄰的兩個隨機數,就可以同時解決上面的兩個問題。
有偽隨機函式f(x) = (x ^ 2 + a) mod N
,其中N是常數,a是隨機生成的常數。
並給出序列x1 = c, x2 = f(x1), x3 = f(x2) ...
。
(原文沒有解釋為什麼這個函式可以替換上述機制)
GCD
同時我們可以優化檢測手段:對於兩個隨機數xi, xj,我們不檢測xi - xj
整除n,而是檢測GCD(xi - xj, n) > 1
。
為什麼?因為只有p和q整除n,而GCD(xi - xj, n)
適用於所有的x = xi - xj
x = p, = 2p, = 3p ... = (q - 1) * p
x = q, = 2q, = 3q ... = (p - 1) * q
(p * q不再內,因為xj <= xi < n)
共有p + q - 2
個。
判環
看似大功告成了,不過我們引入的偽隨機函式f還有問題,f生成的數的軌跡有可能有環(這也是演算法名字中Rho(ρ)的來歷)。也就是對f的不斷迭代可能陷入一個死迴圈。
為此我們需要在終點未知而空間有限的條件下判斷是否陷入環中。
好在這個比較簡單,我們可以用Floyd的判環法:設想有兩個人在跑道上同時出發,同向奔跑,一個人的速度是另一個人的兩倍,那麼它們必然相遇。(快的人比慢的人多跑一圈)
如果發現了有環,可以重新(隨機)給出常數x1 = c
,再次執行演算法。
原文最後的程式碼
a := 2;
b := 2;
while ( b != a )
a = f(a); // a runs once
b = f(f(b)); // b runs twice as fast.
p = GCD( | b - a | , N);
if ( p > 1)
return "Found factor: p";
end
return "Failed. :-("
相關文章
- Pollard-Rho學習筆記筆記
- 【快速因數分解】Pollard's Rho 演算法演算法
- Quick-3.3 開發筆記UI筆記
- PostgreSQL 速查、備忘手冊 | PostgreSQL Quick Find and TutorialSQLUI
- Quick cocos2dx學習筆記UI筆記
- Manacher's Algorithm 馬拉車演算法Go演算法
- Godot Breakeys Godot Beginner Tutorial 遊戲開發筆記Go遊戲開發筆記
- django rest framework個人學習筆記(三)————Tutorial1.SerializationDjangoRESTFramework筆記
- rman b14193Backup and Recovery Quick Start Guide筆記GUIIDE筆記
- 《algorithm-note》演算法筆記中文版正式釋出!Go演算法筆記
- 找到最長迴文字串 - Manacher's Algorithm字串Go
- django rest framework個人學習筆記(四)————Tutorial2.Request and ResponseDjangoRESTFramework筆記
- What’s New in Swift 3? 筆記Swift筆記
- 簡單的量子演算法(二):Simon's Algorithm演算法Go
- Sun Qian's 學習筆記筆記
- k8s學習筆記K8S筆記
- dell筆記本維修 PP05S筆記
- Prim‘s algorithm : 求一個Graph的MST的C++版本GoC++
- algorithmGo
- k8s筆記5--k8s常見命令K8S筆記
- 翻譯:TORN@DO's Cracking Tutorial for (4千字)
- s3-api閱讀筆記(待整理)S3API筆記
- MIT6S081課程筆記MIT筆記
- Veritas Quick I/O and Cached Quick I/OUI
- Kruskal algorithmGo
- WWDC18 What’s New in LLVM 個人筆記LVM筆記
- docker筆記19-k8s的介紹Docker筆記K8S
- docker筆記25-k8s-service資源Docker筆記K8S
- Networking from the container's point of view 筆記AIView筆記
- Warshall‘s algorithm 演算法的實現及優化(修改版)Go演算法優化
- JavaScript TutorialJavaScript
- docker筆記21-k8s的使用入門Docker筆記K8S
- D-S證據理論學習筆記(一)筆記
- S D K 學 習 筆 記1 sdk基礎 (轉)
- Quick lime plantUI
- 在windows下使用s3cmd和s3browser來管理amazon s3的筆記Windowss3cmd筆記
- Expectation Maximization AlgorithmGo
- Branch and Bound AlgorithmGo