POJ1811 Prime Test (Pollard-Rho演算法)
阿新 • • 發佈:2018-12-31
顯然,這麼大的資料不能用樸素演算法過。
需要用到一種叫做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;
}