POJ 1811 Prime Test
题意:对于一个大整数,判断是否质数,如果不是质数输出最小质因子。
解法:判断质数使用Miller-Rabin测试,分解质因子使用Pollard-Rho,Miller-Rabin测试用的红书模板,将测试集根据matrix67的博客进行了拓展,不过也可以随机取的样子,Pollard-Rho用的kuangbin的模板。
代码:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string> #include<string.h> #include<math.h> #include<limits.h> #include<time.h> #include<stdlib.h> #include<map> #include<queue> #include<set> #include<stack> #include<vector> #define LL long long using namespace std; LL ans = LLONG_MAX; LL MUL(LL x, LL n, LL p)//乘法取模 { LL ret = 0; LL base = x; while(n) { if(n & 1) ret = (ret + base) % p; base = (base + base) % p; n >>= 1; } return ret; } LL POW(LL x, LL n, LL p)//快速幂取模 { LL base = x; LL ret = 1; while(n) { if(n & 1) ret = MUL(ret, base, p) % p; base = MUL(base, base, p) % p; n >>= 1; } return ret; } bool test(LL n, LL a, LL d) { if(n == 2) return true; if(n == a) return true; if((n & 1) == 0) return false; while(!(d & 1)) d = d >> 1; LL t = POW(a, d, n); while((d != n - 1) && (t != 1) && (t != n - 1)) { t = t * t % n; d <<= 1; } return (t == n - 1 || (d & 1) == 1); } bool isPrime(LL n)//Miller-Rabin测试 { if(n < 2) return false; LL a[] = {2, 3, 5, 7, 11, 13, 17, 61, 24251};//测试集,据说1e16内的整数都可以 for(int i = 0; i < 9; i++) if(!test(n, a[i], n - 1)) return false; return true; } LL gcd(LL a, LL b)//一开始用的__gcd,后来发现好像有负数参数的样子……只好老老实实手写 { if(a == 0) return 1LL; if(a < 0) return gcd(-a, b); while(b) { LL t = a % b; a = b; b = t; } return a; } LL pollardRho(LL x, LL c) { LL i = 1, k = 2; LL x0 = rand() % x; LL y = x0; while(1) { //cout << i << endl; i++; x0 = (MUL(x0, x0, x) + c) % x; LL d = gcd(y - x0, x); if(d != 1 && d != x) return d; if(y == x0) return x; if(i == k) {y = x0; k += k;} } } void findFac(LL n) { if(isPrime(n)) { //cout << n << endl; ans = min(ans, n); return ; } LL p = n; while(p >= n) p = pollardRho(p, rand() % (n - 1) + 1); findFac(p); findFac(n / p); } int main() { int T; while(~scanf("%d", &T)) { while(T--) { ans = LLONG_MAX; LL n; scanf("%lld", &n); if(isPrime(n)) { puts("Prime"); continue; } findFac(n); printf("%lld\n", ans); } } return 0; }