poj1811(pollard_rho模板)
Posted ygeloutingyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj1811(pollard_rho模板)相关的知识,希望对你有一定的参考价值。
题目链接: http://poj.org/problem?id=1811
题意: 判断一个数 n (2 <= n < 2^54)是否为质数, 是的话输出 "Prime", 否则输出其第一个质因子.
思路: 大数质因子分解, 直接用 pollard_rho (详情参见: http://blog.csdn.net/maxichu/article/details/45459533) 模板即可.
代码:
1 #include <iostream> 2 #include <algorithm> 3 #define ll long long 4 using namespace std; 5 6 const int MAXN = 1e2; 7 const int repeat = 8;//repeat为检测次数,判断错误率为4^-repeat,一般8~10就够了 8 9 ll get_mult(ll a, ll b, ll c){//返回a*b%c 10 a %= c; 11 b %= c; 12 ll ret = 0; 13 while(b){ 14 if(b & 1){ 15 ret += a; 16 if(ret >= c) ret -= c; 17 } 18 b >>= 1; 19 a <<= 1; 20 if(a >= c) a -= c; 21 } 22 return ret; 23 } 24 25 ll get_pow(ll x, ll n, ll mod){//返回x^n%mod 26 ll ret = 1; 27 x %= mod; 28 while(n){ 29 if(n & 1) ret = get_mult(ret, x, mod); 30 x = get_mult(x, x, mod); 31 n >>= 1; 32 } 33 return ret; 34 } 35 36 //通过 a^(n-1) = 1(mod n) 来判断n是否为素数 37 //n-1 = x*2^t 中间使用二次探测定理 38 //是合数返回true,不一定是合数返回false 39 bool cherk(ll a, ll n, ll x, ll t){ 40 ll ret = get_pow(a, x, n); 41 ll last = ret; 42 for(int i = 1; i <= t; i++){ 43 ret = get_mult(ret, ret, n); 44 if(ret == 1 && last != 1 && last != n - 1) return true; 45 last = ret; 46 } 47 if(ret != 1) return true; 48 return false; 49 } 50 51 bool Miller_Rabin(ll n){ 52 if(n < 2) return false; 53 if(n == 2) return true; 54 if(!(n & 1)) return false;//偶数 55 ll x = n - 1, t = 0; 56 while(!(x & 1)){ 57 x >>= 1; 58 t++; 59 } 60 // srand(time(NULL)); 61 for(int i = 0; i < repeat; i++){ 62 ll a = rand() % (n - 1) + 1; 63 if(cherk(a, n, x, t)) return false; 64 } 65 return true; 66 } 67 68 ll factor[MAXN]; 69 int tot;//n的质因子个数 70 71 ll get_gcd(ll a, ll b){ 72 ll tmp; 73 while(b){ 74 tmp = a; 75 a = b; 76 b = tmp % b; 77 } 78 return a >= 0 ? a : -a; 79 } 80 81 ll pollard_rho(ll x, ll c){//返回x的一个因子 82 ll i = 1, k = 2; 83 // srand(time(NULL)); 84 ll x0 = rand() % (x - 1) + 1; 85 ll y = x0; 86 while(1){ 87 i++; 88 x0 = (get_mult(x0, x0, x) + c) % x; 89 ll d = get_gcd(y - x0, x); 90 if(d != 1 && d != x) return d; 91 if(y == x0) return x; 92 if(i == k){ 93 y = x0; 94 k += k; 95 } 96 } 97 } 98 99 void findfac(ll n, int k){//对n质因分解并将结果保存到factor中 100 if(n == 1) return; 101 if(Miller_Rabin(n)){ 102 factor[tot++] = n; 103 return; 104 } 105 ll p = n; 106 int c = k;//c防止死循环 107 while(p >= n){ 108 p = pollard_rho(p, c--); 109 } 110 findfac(p, k); 111 findfac(n / p, k); 112 } 113 114 int main(void){ 115 ll n; 116 int t; 117 cin >> t; 118 while(t--){ 119 cin >> n; 120 if(Miller_Rabin(n)) cout << "Prime" << endl; 121 else{ 122 tot = 0; 123 findfac(n, 107); 124 ll sol = factor[0]; 125 for(int i = 1; i < tot; i++){ 126 sol = min(sol, factor[i]); 127 } 128 cout << sol << endl; 129 } 130 } 131 return 0; 132 }
以上是关于poj1811(pollard_rho模板)的主要内容,如果未能解决你的问题,请参考以下文章
数学#素数判定Miller_Rabin+大数因数分解Pollard_rho算法 POJ 1811&2429
随机素数测试(Miller_Rabin算法)和求整数素因子(Pollard_rho算法)
poj 2429GCD & LCM Inverse (Miller-Rabin素数测试和Pollard_Rho_因数分解)