Pollard Rho大質數分解學習筆記
目錄
- 問題
- 流程
- 代碼
- 生日悖論
- end
問題
給定n,要求對n質因數分解
普通的試除法已經不能應用於大整數了,我們需要更快的算法
流程
大概就是找出\(n=c*d\)
如果\(c\)是素數,結束,不是繼續遞歸處理。
具體一點的話
1.先對n進行\(miller\_rabin\)測試,是素數就直接結束了
如果不會的話,看我前篇博客的介紹吧
為何還要多寫個\(miller\_rabin\),他沒有非平凡因子,他要保證復雜度?
2.隨機基底a和c,生成序列\(x_{0}=a,x_{i}=x_{i-1}^{2}+c(mod n)\)
3.若出現\((x_{i}-x_{2i+1},n)≠1\),停止算法,令\(d=(x_{i}-x_{2i+1},n)\),若\(d≠n\),那d就是n的非平凡因子,n被分為d和n/d相乘的結果,遞歸下去繼續分解
4.若d=n,重選基底a和c,重復過程(出現循環了)
劉汝佳先生說:想象一下,假設有兩個小孩子在一個“可以無限向前跑”的跑道上賽跑,同時出發。但其中一個小孩的速度是另一個的兩倍。如果跑道是直的,跑得快的小孩永遠在前面;但如果跑道有環,則跑得快的小孩將“追上”跑得慢的小孩。
算法復雜度\(O(n^{ \frac {1}{4} }*pro)\)
具體的我也不知道咋證
代碼
#include <bits/stdc++.h> using namespace std; const int maxn = 10005; typedef long long LL; LL fpm(LL a, LL k, LL p) //calc a^k % p { LL res = 1; for (; k ; k >>= 1, a = a * a % p) if (k & 1) res = a * res % p; return res; } int prime[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29}; bool detective(LL a, LL n) { int r = 0; LL d = n - 1; // n - 1 = 2 ^ r * d while (d % 2 == 0) d >>= 1, ++r; for (LL x = fpm(a, d, n), y; r ; r--) { y = x * x % n; if (y == 1) { if (x == 1) return true; if (x == n - 1) return true; return false; } x = y; } return false; } bool miller_rabin(LL n) { for (int i = 0; i < 10; i++) { if (n == prime[i]) return true; if (n % prime[i] == 0) return false; if (!detective(prime[i], n)) return false; } return true; } vector<LL> res; int irand() {return rand() << 15 ^ rand();} LL irand(LL n) {return (((LL) irand()) << 30 ^ irand()) % n;} LL mul(LL a, LL b, LL n) {return (a * b - (LL) ((long double) a * b / n + 1e-9) * n) % n;} LL rho(LL n) { LL a = irand(n), c = irand(n); LL x = a, y = (mul(a, a, n) + c) % n; LL z = x > y ? x - y: y - x; LL d = __gcd(z, n); while (d == 1) { x = (mul(x, x, n) + c) % n; y = (mul(y, y, n) + c) % n; y = (mul(y, y, n) + c) % n; z = x > y ? x - y: y - x; d = __gcd(z, n); } return d; } void pollard_rho(LL n) { if (n == 1) return ; if (miller_rabin(n)) {res.push_back(n); return ;} LL d = n; while (d == n) d = rho(n); pollard_rho(d); pollard_rho(n / d); } int main() { pollard_rho(997 * 131ll * 6ll * 50ll * 79ll * 97 * 12132); for (auto x: res) cerr << x << " " ; }
生日悖論
(當然,我們這裏的一年是穩定365天,和我們不一樣)
23個人中至少有一對兩個人生日相同的概率在一半以上,感覺不可思議吧,與我們自我感覺的有很大差異,其實,當我們看到“有人生日相同”時,下意識地會用“與我生日相同”去推測,直覺就讓我們直覺產生了“兩人生日相同”概率很小。理性計算的結果與日常經驗產生了如此明顯的矛盾,所以叫做“生日悖論”。
可以說,直覺沒有錯,錯的是我們沒有正確地去理解問題。因此,當我們剝開直覺的謊言,看清事實的那一刻,才會覺得如此不可思議。
我們的問題是“任意兩個人的生日相同的概率”(所以要理性分析呀qwq)。
我們討論兩個人生日相同的情況。
總概率是365*365,生日不同的情況\(365*364\)
那生日相同的情況就是 \(\frac{365*365-365*364}{365*365}=\frac{1}{365}\)
四個人同理\(\frac{365^4-\frac{365!}{361!}}{365^4}\)
再大一點可以用long double 計算,可以算出23人時概率就大於一半了
end
好多摘抄的呀qwq,在這裏鳴謝好多好多的網上資料
Pollard Rho大質數分解學習筆記