数学--数论--随机算法--Pollard Rho 大数分解算法 (带输出版本)
生活随笔
收集整理的這篇文章主要介紹了
数学--数论--随机算法--Pollard Rho 大数分解算法 (带输出版本)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
RhoPollard Rho是一個(gè)著名的大數(shù)質(zhì)因數(shù)分解算法,它的實(shí)現(xiàn)基于一個(gè)神奇的算法:MillerRabinMillerRabin素?cái)?shù)測(cè)試。
操作流程
首先,我們先用MillerRabinMillerRabin判斷當(dāng)前數(shù)xx是否為質(zhì)數(shù),若是,則可直接統(tǒng)計(jì)信息并退出函數(shù)
然后是各種證明及優(yōu)化,我覺得不大實(shí)用,這個(gè)板子是我改了很多遍了,也過了很多題的板子。用著很舒服,無(wú)論卡常,不卡常,速度相差不大,也可以加read.
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll pr; ll pmod(ll a, ll b, ll p) { return (a * b - (ll)((long double)a / p * b) * p + p) % p; } //普通的快速乘會(huì)T ll gmod(ll a, ll b, ll p) {ll res = 1;while (b){if (b & 1) res = pmod(res, a, p);a = pmod(a, a, p);b >>= 1;}return res; } inline ll gcd(ll a, ll b) { //聽說(shuō)二進(jìn)制算法特快if (!a) return b;if (!b)return a;int t = __builtin_ctzll(a | b);a >>= __builtin_ctzll(a);do{b >>= __builtin_ctzll(b);if (a > b){ll t = b;b = a, a = t;}b -= a;} while (b);return a << t; } bool Miller_Rabin(ll n) {if (n == 46856248255981ll || n < 2)return false; //強(qiáng)偽素?cái)?shù)if (n == 2 || n == 3 || n == 7 || n == 61 || n == 24251)return true;if (!(n & 1) || !(n % 3) || !(n % 61) || !(n % 24251))return false;ll m = n - 1, k = 0;while (!(m & 1))k++, m >>= 1;for (int i = 1; i <= 20; ++i) // 20為Miller-Rabin測(cè)試的迭代次數(shù){ll a = rand() % (n - 1) + 1, x = gmod(a, m, n), y;for (int j = 1; j <= k; ++j){y = pmod(x, x, n);if (y == 1 && x != 1 && x != n - 1)return 0;x = y;}if (y != 1)return 0;}return 1; } ll Pollard_Rho(ll x) {ll n = 0, m = 0, t = 1, q = 1, c = rand() % (x - 1) + 1;for (ll k = 2;; k <<= 1, m = n, q = 1){for (ll i = 1; i <= k; ++i){n = (pmod(n, n, x) + c) % x;q = pmod(q, abs(m - n), x);}t = gcd(x, q);if (t > 1)return t;} } void fid(ll n) {if (n == 1)return;if (Miller_Rabin(n)){pr = max(pr, n);return;}ll p = n;while (p >= n)p = Pollard_Rho(p);fid(p);fid(n / p); } int main() {int T;ll n;scanf("%d", &T);while (T--){scanf("%lld", &n);pr = 0;fid(n);if (pr == n)puts("Prime");elseprintf("%lld\n", pr);}return 0; }帶輸出的我也寫了
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll pr; ll pmod(ll a, ll b, ll p) { return (a * b - (ll)((long double)a / p * b) * p + p) % p; } //普通的快速乘會(huì)T ll gmod(ll a, ll b, ll p) {ll res = 1;while (b){if (b & 1)res = pmod(res, a, p);a = pmod(a, a, p);b >>= 1;}return res; } inline ll gcd(ll a, ll b) { //聽說(shuō)二進(jìn)制算法特快if (!a)return b;if (!b)return a;int t = __builtin_ctzll(a | b);a >>= __builtin_ctzll(a);do{b >>= __builtin_ctzll(b);if (a > b){ll t = b;b = a, a = t;}b -= a;} while (b);return a << t; } bool Miller_Rabin(ll n) {if (n == 46856248255981ll || n < 2)return false; //強(qiáng)偽素?cái)?shù)if (n == 2 || n == 3 || n == 7 || n == 61 || n == 24251)return true;if (!(n & 1) || !(n % 3) || !(n % 61) || !(n % 24251))return false;ll m = n - 1, k = 0;while (!(m & 1))k++, m >>= 1;for (int i = 1; i <= 20; ++i) // 20為Miller-Rabin測(cè)試的迭代次數(shù){ll a = rand() % (n - 1) + 1, x = gmod(a, m, n), y;for (int j = 1; j <= k; ++j){y = pmod(x, x, n);if (y == 1 && x != 1 && x != n - 1)return 0;x = y;}if (y != 1)return 0;}return 1; } ll Pollard_Rho(ll x) {ll n = 0, m = 0, t = 1, q = 1, c = rand() % (x - 1) + 1;for (ll k = 2;; k <<= 1, m = n, q = 1){for (ll i = 1; i <= k; ++i){n = (pmod(n, n, x) + c) % x;q = pmod(q, abs(m - n), x);}t = gcd(x, q);if (t > 1)return t;} } map<long long, int> m; void fid(ll n) {if (n == 1)return;if (Miller_Rabin(n)){pr = max(pr, n);m[n]++;return;}ll p = n;while (p >= n)p = Pollard_Rho(p);fid(p);fid(n / p); } int main() {int T;ll n;scanf("%d", &T);while (T--){m.clear();scanf("%lld", &n);pr = 0;fid(n);if (pr == n)puts("Prime");else{printf("%lld\n", pr);for (map<long long, int>::iterator c = m.begin(); c != m.end();){printf("%lld^%d", c->first, c->second);if ((++c) != m.end())printf(" * ");}printf("\n");}}return 0; }總結(jié)
以上是生活随笔為你收集整理的数学--数论--随机算法--Pollard Rho 大数分解算法 (带输出版本)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 末日时钟被拨快10秒 系有史以来最接近世
- 下一篇: 数学--数论--随机算法--Pollar