Miller_Rabbin&&Pollard_Rho
前言
Miller Rabin 算法是一种高效的质数判断方法。虽然是一种不确定的质数判断法,但是在选择多种底数的情况下,正确率是可以接受的。
Pollard Rho是一个非常玄学的方式,用于在\(O(n^\frac{1}{4})\)的期望时间复杂度内计算合数\(n\)的某个非平凡因子。事实上算法导论给出的是\(O(\sqrt{p})\),\(p\)是\(n\)的某个最小因子,满足\(p\)与\(n/p\)互质。但是这些都是期望,未必符合实际。但事实上Pollard Rho算法在实际环境中运行的相当不错。
Miller_Rabbin算法
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int p[10]={2,3,5,7,11,13,17,19,61,24251};
LL quick(LL a,LL b,LL mod)
{
LL res=1;
while(b)
{
if(b&1)res=((__int128)res*a)%mod;
a=((__int128)a*a)%mod;
b>>=1;
}
return res;
}
bool mr(LL x,LL b)
{
LL k=x-1;
while(k)
{
LL cur=quick(b,k,x);
if(cur!=1&&cur!=x-1)return false;
if((k&1)||cur==x-1)return true;
k>>=1;
}
return true;
}
bool prime(LL x)
{
if(x==1)return false;
for(int i=0;i<10;i++)
{
if(x==p[i])return true;
if(!mr(x,p[i]))return false;
}
return true;
}
int main()
{
LL x;
while(~scanf("%lld",&x))
{
if(prime(x))printf("Y\n");
else printf("N\n");
}
return 0;
}
Pollard_Rho算法
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef __int128 LLL;
LL maxfac;
int p[10]={2,3,5,7,11,13,17,19,61,24251};
LL gcd(LL a,LL b)
{
return b==0?a:gcd(b,a%b);
}
LL quick(LL a,LL b,LL mod)
{
LL res=1;
while(b)
{
if(b&1)res=((LLL)res*a)%mod;
a=((LLL)a*a)%mod;
b>>=1;
}
return res;
}
bool mr(LL x,LL b)
{
LL k=x-1;
while(k)
{
LL cur=quick(b,k,x);
if(cur!=1&&cur!=x-1)return false;
if((k&1)||cur==x-1)return true;
k>>=1;
}
return true;
}
bool prime(LL x)
{
if(x==1)return false;
for(int i=0;i<10;i++)
{
if(x==p[i])return true;
if(!mr(x,p[i]))return false;
}
return true;
}
LL PR(LL x)
{
LL s=0,t=0,c=1LL*rand()%(x-1)+1;
for(int goal=1;;goal<<=1)
{
s=t;
LL val=1;
for(int stp=1;stp<=goal;stp++)
{
t=((LLL)t*t+c)%x;
val=(LLL)val*abs(t-s)%x;
if(stp%127==0)
{
LL d=gcd(val,x);
if(d>1)return d;
}
}
LL d=gcd(val,x);
if(d>1)return d;
}
}
void fac(LL x)
{
if(x<=maxfac||x<2)return;
if(prime(x))
{
maxfac=x;
return;
}
LL p=x;
while(p>=x)p=PR(x);
while(x%p==0)x/=p;
fac(x);fac(p);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
srand((unsigned)time(NULL));
LL x;
scanf("%lld",&x);
maxfac=0;
fac(x);
if(maxfac==x)printf("Prime\n");
else printf("%lld\n",maxfac);
}
}