POJ1811 Prime Test(Miller-Rabin素数测试算法与Pollard Rho因子分解算法)
题意:给出一个N(2 <= N < 2^54),如果是素数,输出"Prime",否则输出最小的素因子
#include <iostream> //该程序为哥德巴赫猜(想输出所有的组合) #include <cmath> #include <cstdlib> #include <ctime> #include <cstdio> #include <algorithm> using namespace std; typedef unsigned long long ull; typedef unsigned long long LL; LL n,ans,factor[10001];//质因数分解结果(刚返回时是无序的) LL tol;//质因数的个数,数组下标从0开始 LL prime[6] = {2, 3, 5, 233, 331}; LL qmul(LL x, LL y, LL mod) { // 乘法防止溢出, 如果p * p不爆LL的话可以直接乘; O(1)乘法或者转化成二进制加法 //快速乘法取模算法 return (x * y - (long long)(x / (long double)mod * y + 1e-3) *mod + mod) % mod; /* LL ret = 0; while(y) { if(y & 1) ret = (ret + x) % mod; x = x * 2 % mod; y >>= 1; } return ret; */ } LL qpow(LL a, LL n, LL mod) { LL ret = 1; while(n) { if(n & 1) ret = qmul(ret, a, mod); a = qmul(a, a, mod); n >>= 1;//n=n/2二进制乘除法 } return ret; } bool Miller_Rabin(LL p) { if(p < 2) return 0; if(p != 2 && p % 2 == 0) return 0; LL s = p - 1; while(! (s & 1)) s >>= 1;//排除掉偶数 for(int i = 0; i < 5; ++i) { if(p == prime[i]) return 1; LL t = s, m = qpow(prime[i], s, p); //二次探测定理卡米歇尔数保证该数为素数 //卡米歇尔数若一个数为合数当0<x<p,则方程x^p≡a(mod p) //二次探测定理如果p是一个素数,0<x<p,则方程x^2≡1(mod p)的解为x=1,p-1 while(t != p - 1 && m != 1 && m != p - 1) { m = qmul(m, m, p); t <<= 1; } if(m != p - 1 && !(t & 1)) return 0;//不是奇数且m!=p-1 } return 1; } LL gcd(LL a,LL b) { if(a==0)return 1; if(a<0) return gcd(-a,b); while(b) { long long t=a%b; a=b; b=t; } return a; } LL Pollard_rho(LL x,LL c) { LL i=1,k=2; LL x0=rand()%x; LL y=x0; while(1) { i++; x0=(qmul(x0,x0,x)+c)%x; long long d=gcd(y-x0,x); if(d!=1&&d!=x) return d; if(y==x0) return x; if(i==k) { y=x0; k+=k; } } } //对n进行素因子分解 void findfac(LL n) { if(Miller_Rabin(n))//素数 { factor[tol++]=n; return; } LL p=n; while(p>=n) p=Pollard_rho(p,rand()%(n-1)+1); findfac(p);//递归调用 findfac(n/p); } int main() { int T; long long x; ios::sync_with_stdio(false);cin.tie(0); cin>>T; while(T--) { cin>>x; if(Miller_Rabin(x)) cout<<"Prime"<<endl; else { tol=0; findfac(x); long long ans=factor[0]; for(int i=1;i<tol;i++) if(ans>factor[i]) ans=factor[i]; cout<<ans<<endl; } } }
Pollard Rho因子分解算法:https://www.cnblogs.com/dalt/p/8437119.html