1. 程式人生 > >POJ1811 Prime Test (Pollard-Rho演算法)

POJ1811 Prime Test (Pollard-Rho演算法)

顯然,這麼大的資料不能用樸素演算法過。
需要用到一種叫做Pollard-Rho的演算法。
Pollard-Rho演算法戳這裡

看懂了就變成了裸題。。。
直接上程式碼:

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;

const int MAXN = 65;
long long x[MAXN], ans;

long long multi(long long a, long long b, long long p) {
    long long
ans = 0; while(b) { if(b&1LL) ans = (ans+a)%p; a = (a+a)%p; b >>= 1; } return ans; } long long qpow(long long a, long long b, long long p) { long long ans = 1; while(b) { if(b&1LL) ans = multi(ans, a, p); a = multi(a, a, p); b >>= 1
; } return ans; } bool Miller_Rabin(long long n) { if(n == 2) return true; int s = 20, i, t = 0; long long u = n-1; while(!(u & 1)) { t++; u >>= 1; } while(s--) { long long a = rand()%(n-2)+2; x[0] = qpow(a, u, n); for(i = 1
; i <= t; i++) { x[i] = multi(x[i-1], x[i-1], n); if(x[i] == 1 && x[i-1] != 1 && x[i-1] != n-1) return false; } if(x[t] != 1) return false; } return true; } long long gcd(long long a, long long b) { return b ? gcd(b, a%b) : a; } long long Pollard_Rho(long long n, int c) { long long i = 1, k = 2, x = rand()%(n-1)+1, y = x; while(true) { i++; x = (multi(x, x, n) + c)%n; long long p = gcd((y-x+n)%n, n); if(p != 1 && p != n) return p; if(y == x) return n; if(i == k) { y = x; k <<= 1; } } } void find(long long n, int c) { if(n == 1) return; if(Miller_Rabin(n)) { ans = min(ans, n); return; } long long p = n, k = c; while(p >= n) p = Pollard_Rho(p, c--); find(p, k); find(n/p, k); } int main() { long long n, i; int t; scanf("%d", &t); while(t--) { ans = 1LL<<62; scanf("%lld", &n); find(n, 120); if(ans == n) printf("Prime\n"); else printf("%lld\n", ans); } return 0; }