Miller-rabin & Pollard-Rho

Miller-rabin

米勒罗宾,素数探测

  1. 小费马定理,本质是欧拉定理的特殊情况
    即p为质数是\(a^{(p-1)} \equiv 1 \pmod p\)d的充分条件
  2. \(x^2 \equiv 1 \pmod p\)\(x \equiv 1or-1 \pmod p\)

于是把p-1分解成 \(2^k*t\)
从t开始往上自乘,每次指数*2,直到\(2^k\)
如果中间有不满足②的情况,为合数

最后再判断是否等于1(条件①)

用十个质数筛一筛就很稳,5个也行

Pollard-Rho算法

筛质因子的

先判断要处理的数是不是质数(Miller-rabin)

不是的话每次随机一个数(用数列\(f_{(i)}=f_{(i-1)}*f_{(i-1)}+c \pmod x\)两项的差)判断他和x的gcd是否不为1和n,可以的话递归处理

复杂度\(O(n^{\frac{1}{4}})\)

#include<bits/stdc++.h>
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define ll __int128
#pragma GCC diagnostic error "-std=c++14"
#pragma GCC target("avx")
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
ll test[15]={0,2,61,23,37};
inline ll read(){
	ll x=0;char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) if(ch==EOF) return -1;
	for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
	return x;
}
ll x;
inline ll quick_pow(ll a,ll b,ll mod){
	ll na=1;
	while(b){
		if(b&1) na=(na*a)%mod;
		a=(a*a)%mod;
		b>>=1;
	}
	return na;
}
inline ll MB(ll now){
	if(now==1) return 0;
	ll t=now-1,k=0;
	while(!(t&1)) k++,t>>=1;
	rep(i,1,4){
		if(now==test[i]) return 1;
		ll a=quick_pow(test[i],t,now),tmp=a;
		rep(j,1,k){
			tmp=(a*a)%now;
			if(tmp==1&&a!=1&&a!=now-1) return 0;
			a=tmp;
		} 
		if(a!=1) return 0;
	}
	return 1;
}
inline ll gcd(ll a,ll b){
	if(b==0) return a;
	else return gcd(b,a%b); 
}
void out (ll x){
	if(x>9) out(x/10);
	putchar(x%10+'0');
}
inline ll abss(ll aa){
	return aa>0?aa:-aa;
}
inline ll Irand(ll x){
    return (ll)((rand()<<15^rand())<<30^(rand()<<15^rand()))%x;
}
ll ans=0;
inline ll get(ll x){
    register ll c=Irand(x) ;
    register ll t1=Irand(x),t2=t1*t1%x+c ; 
    register ll dif=t1>t2?(t1-t2):(t2-t1),G=gcd(x,dif) ;
    while (G == 1){
        t1=t1*t1%x+c;if (t1>=x) t1%=x;
        t2=t2*t2%x+c;t2=t2*t2%x+c;if (t2>=x) t2%=x;
		dif=t1>t2?(t1-t2):(t2-t1),G=gcd(x,dif);
    }
    return G ;
}
inline void work(ll x){
	if(x<=ans) return;
	if(MB(x)){
		ans=ans>x?ans:x;
		return;
	} 
	ll y=x;
	while(y==x) y=get(x);
	while(x%y==0){
		x/=y;
	} 
	work(y);work(x);
}
ll n;
int main(){
	n=read();
	for(register int i=1;i<=n;i++){
		x=read();
		if(MB(x)) printf("Prime\n");
		else{
			ans=0;
			work(x);
			out(ans),putchar(10);
		}
	}
	return 0;
}
posted @ 2019-07-27 23:11  lcyfrog  阅读(236)  评论(0编辑  收藏  举报