BZOJ 3667: Rabin-Miller算法

Description

大数因数分解.\(n\leqslant 2^{64}\)

Solution

Miller_Rabin+Pollard_rho...

Miller_Rabin素数判定就是随机一个数,根据小费马定理

\(a^{p-1}\equiv  1 \mod p\)

若\(p\)是一个奇素数,那么\(p-1\)可以分解成\(r\times 2^s\)的形式

因为\(x^2\equiv 1 \mod p\)那么 \(x\equiv \pm 1 \mod p\)检查是否存在这个\(x\)...

Pollard_rho

根据生日悖论还是什么东西的...随机\(k\)个数差为\(t\)是的概率很大...

然后判断和\(p\)的\(gcd\),然后不断递归分解...

Code

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

namespace NT {
	inline LL Mul(LL a,LL b,LL p){
		if(p<=1000000000) return a*b%p;
		return (a*b-(LL)(a/(long double)p*b+1e-3)*p+p)%p;
	}
	inline LL Pow(LL a,LL b,LL p,LL r=1) { for(;b;b>>=1,a=Mul(a,a,p))
		if(b&1) r=Mul(r,a,p);return r; }
	int chk(LL a,LL d,LL s,LL p) {
		a=Pow(a,d,p),d=a;
		for(int i=1;i<=s;i++) {
			a=Mul(a,a,p);
			if(a==1 && d!=p-1 && d!=1) return 0;
			d=a;
		}return a==1;
	}
	int MR(LL p) {
		if(p<=1) return 0;
		if(p==2) return 1;
		if(!(p&1)) return 0;
		LL d=p-1,s=0;
		for(;!(d&1);d>>=1,s++);
		for(int i=0;i<10;i++) if(!chk(rand()%(p-1)+1,d,s,p)) return 0;
		return 1;
	}
	LL gcd(LL a,LL b) { return !b?a:gcd(b,a%b); }
	LL Div(LL p,LL c) {
		LL x=rand()%p,y=x,t=1;
		for(int i=1,k=2;t==1;i++) {
			x=(Mul(x,x,p)+c)%p;
			t=gcd(abs(x-y),p);
			if(i==k) y=x,k<<=1;
		}return t;
	}
	void PR(LL p,LL &mx) {
		if(p==1) return;
		if(MR(p)) { mx=max(mx,p);return; }
		LL tmp=p;
		for(;tmp==p;tmp=Div(p,rand()%(p-1)+1));
		PR(tmp,mx),PR(p/tmp,mx);
	}
}

int T;
LL x,mx;
int main() {
	for(scanf("%d",&T);T--;) {
		scanf("%lld",&x);
		mx=0;
		NT::PR(x,mx);
		if(mx==x) puts("Prime");
		else printf("%lld\n",mx);
	}
	return 0;
}

  

posted @ 2017-04-19 09:38  北北北北屿  阅读(215)  评论(0编辑  收藏  举报