poj 1811 随机素数和大数分解(模板)
Sample Input
2 5 10
Sample Output
Prime 2
模板学习:
判断是否是素数,数据很大,所以用miller,不是的话再用pollard rho分解
miller : 通过费马小定理,若N为素数,a^(N-1) = 1 (mod N),
再利用二次判定:
若x为素数,0<x<p, x*x = 1(mod q)
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <time.h> #define N 10100 typedef long long ll; using namespace std; const int S = 8; //随机判定次数 一般8 - 10 // a*b%c ll mult_mod(ll a,ll b,ll c) { a %= c; b %= c; ll ret = 0; ll temp = a; while(b) { if(b&1) { ret += temp; if(ret > c) ret -= c; } temp <<= 1; if(temp > c) temp -= c; b >>= 1; } return ret; } // (a^n)%mod ll pow_mod(ll a,ll n,ll mod) { ll ret = 1; ll temp = a%mod; while(n) { if(n & 1) ret = mult_mod(ret,temp ,mod); temp = mult_mod(temp,temp,mod); n>>= 1; } return ret; } //通过费马小定理,a^(n-1)=1(mod n) ;来判断n是否是素数 bool check(ll a,ll n,ll x,ll t) { ll ret = pow_mod(a,x,n); ll last = ret; for(int i = 1; i <= t; i++) { ret = mult_mod(ret,ret,n); //二次探测 if(ret == 1 && last != 1 && last != n-1) return true; last = ret; } if(ret != 1) return true; else return false; } bool miller_rabin(ll n) //随机素数 { if(n < 2) return false; if(n == 2) return true; if((n&1) == 0) return false; //偶数 ll x = n - 1; ll t = 0; while((x&1) == 0) { x>>= 1; t++; }; srand(time(NULL)); //G++时不要 for(int i = 0; i < S; i++) { ll a = rand()%(n - 1) + 1; if(check(a,n,x,t)) return false; } return true; } ll factor[100]; int tol; ll gcd(ll a,ll b) { ll t; while(b) { t = a; a = b; b = t % b; } if(a >= 0) return a; else return -a; } //找因子 ll pollard_rho(ll x,ll c) { ll i = 1,k = 2; srand(time(NULL)); ll x1 = rand()%(x-1)+1; ll y = x1; while(1) { i++; x1 = (mult_mod(x1,x1,x)+c)%x; ll d = gcd(y-x1,x); if(d!=1 && d!=x) return d; if(y == x1) return x; if(i == k) { y = x1; k += k; } } } //对n进行分解,存入数组, void findfac(ll n,int k) //大数分解 { if(n == 1) return ; if(miller_rabin(n)) //判素 { factor[tol++] = n; return ; } ll p = n; int c = k; while( p>= n) p = pollard_rho(p,c--); //防止死循环k,值变换 findfac(p,k); findfac(n/p,k); } int main() { int t; ll n; scanf("%d",&t); while(t--) { scanf("%I64d",&n); if(miller_rabin(n)) printf("Prime\n"); else { tol = 0; findfac(n,107); ll ans = factor[0]; for(int i = 1; i < tol; i++) ans = min(ans,factor[i]); printf("%I64d\n",ans); } } return 0; }