poj 1811 Prime Test(大素數判定和素因子分解)
阿新 • • 發佈:2019-01-04
先用Miller_Rabin演算法進行素數判斷,再用Pollard_rho分解素因子。
今天做TC時,遇到一道大素數判定和質因子分解的模板題。想到了質因子分解,但沒想到用這個模板。賽後,還是自己理解一遍,然後手敲吧。。
#include <stdio.h> #include <iostream> #include <map> #include <set> #include <stack> #include <vector> #include <math.h> #include <string.h> #include <queue> #include <string> #include <stdlib.h> #include <algorithm> #define LL long long #define _LL __int64 #define eps 1e-12 #define PI acos(-1.0) #define C 240 #define S 20 using namespace std; LL fac[100]; int tol; LL gcd(LL a, LL b) { if(a == 0) return 1; if(a < 0) return gcd(-a,b); if(b == 0) return a; return gcd(b,a%b); } LL MultMod(LL a, LL b, LL n) { a %= n; b %= n; LL ret = 0; while(b) { if(b&1) { ret += a; if(ret >= n) ret -= n; } a <<= 1; if(a >= n) a -= n; b >>= 1; } return ret; } LL PowMod(LL a, LL n, LL m) { LL ret = 1; a %= m; while(n) { if(n&1) ret = MultMod(ret,a,m); a = MultMod(a,a,m); n >>= 1; } return ret; } /// 大素數判定 bool Witness(LL a, LL n) { LL t = 0; LL u = n-1; while(!(u&1)) { t++; u = u/2; } LL x0 = PowMod(a,u,n); for(int i = 1; i <= t; i++) { LL x1 = MultMod(x0,x0,n); if(x1 == 1 && x0 != 1 && x0 != (n-1) ) return true; x0 = x1; //之前少了這一句 } if(x0 != 1) return true; return false; } bool Miller_Rabin(LL n) { if(n == 2) return true; if((n&1) == 0) return false; //srand(time(NULL)); for(int i = 0; i < S; i++) { LL a = rand()%(n-1) + 1; if(Witness(a,n)) return false; } return true; } ///質因子分解 LL Pollar_Rho(LL n, LL c) { LL i = 1,x = rand()%n, y = x,k = 2; while(1) { i++; x = ( MultMod(x,x,n)+c)%n; LL d = gcd(y-x,n); if(d != 1 && d != n) return d; if(x == y) return n; if(i == k) { y = x; k = k*2; } } } void get_small(LL n, LL c) { if(n == 1) return; if(Miller_Rabin(n)) { fac[tol++] = n; return; } LL p = n; while(p >= n) p = Pollar_Rho(p,c--); get_small(p,c); get_small(n/p,c); } int main() { int test; LL n; scanf("%d",&test); while(test--) { scanf("%lld",&n); if(Miller_Rabin(n)) { printf("Prime\n"); continue; } tol = 0; get_small(n,C); LL ans = fac[0]; for(int i = 1; i < tol; i++) ans = min(ans,fac[i]); printf("%lld\n",ans); } return 0; }