P4718 【模板】Pollard-Rho算法

题面

传送门

题解

题解

太神仙了学不来orz

//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define dd long double
#define fp(i,a,b) for(int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
const int base[]={2,3,7,61,24251};
inline ll mul(R ll x,R ll y,R ll P){R ll k=(dd)x*y/P;k=x*y-k*P;return k<0?k+P:k;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
inline ll g(R ll x,R ll n,R ll c){x=mul(x,x,n)+c;return x>n?x-n:x;}
inline ll Abs(R ll x){return x<0?-x:x;}
ll ksm(R ll x,R ll y,R ll P){
	R ll res=1;
	for(;y;y>>=1,x=mul(x,x,P))if(y&1)res=mul(res,x,P);
	return res;
}
bool miller(ll x){
	if(x<2||x==46856248255981ll)return false;
	if(x==2||x==3||x==7||x==61||x==24251)return true;
	if(!(x&1)||!(x%3)||!(x%61)||!(x%24251))return false;
	ll p=x-1;int t=0,j;
	while(!(p&1))p>>=1,++t;
	fp(i,0,4){
		if(base[i]>x)break;
		ll res=ksm(base[i],p,x);
		if(res==1||res==x-1)continue;
		for(j=1;j<=t;++j){
			res=mul(res,res,x);
			if(res==x-1)break;
		}
		if(j>t)return false;
	}
	return true;
}
const int M=(1<<7)-1;
ll rho(ll n){
	if(!(n&1))return 2;if(!(n%3))return 3;
	ll x=0,y=x,t=1,q=1,c=rand()%(n-1)+1;
	for(R int k=2;;k<<=1,y=x,q=1){
		fp(i,1,k){
			x=g(x,n,c);
			q=mul(q,Abs(x-y),n);
			if(!(i&M)){
				t=gcd(q,n);
				if(t>1)break;
			}
		}
		if(t>1||(t=gcd(q,n))>1)break;
	}
	return t;
}
ll res;
void find(ll x){
	if(x==1||x<=res)return;
	if(miller(x))return res=x,void();
	ll p=x;
	while(p==x)p=rho(x);
	while(x%p==0)x/=p;
	find(p),find(x);
}
int main(){
	srand(time(0));
//	freopen("testdata.in","r",stdin);
	int T;ll n;scanf("%d",&T);
	while(T--){
		scanf("%lld",&n),res=0,find(n);
		res==n?printf("Prime\n"):printf("%d\n",res);
	}
	return 0;
}
posted @ 2019-02-25 18:52  bztMinamoto  阅读(323)  评论(0编辑  收藏  举报
Live2D