Miller-rabin

Miller-rabin

米勒罗宾,素数探测

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

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

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

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

Pollard-Rho算法

筛质因子的

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

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

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

#include
#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;
}

你可能感兴趣的:(数论——miller,rabin)