Pollard-Rho算法学习笔记
\(Pollard-Rho\)算法学习笔记
我愿称之为\(RP\)算法
算是咕咕咕了很久的一个知识点,今天补一补(主要是\(T2\)考了就很寄)
好像我昨天跳到了这个题时候说\(:\)这个东西谁也不会考吧。今天就开幕雷击了
首先是\(Miller-Rabin\)判断素性
一个玄学(基于随机的算法),莫名很喜欢这个算法。。。
常用的判断素性方法,\(O(\sqrt n)\)暴力枚举,\(n<=10^{18}\)完美\(TLE\)
基础数论里面的费马小定理
\(a^{\phi(p)-1}=1(\mod p)\)当\((1<=a<p)\)
逆否命题成立,假如存在\((1<=a<p)a^{p-1}\neq 1\),那么\(p\)不为质数
我们可以随机选择数字,快速幂判断素性
但是即使满足了所有\((1<=a<p)a^{p-1}=1(\mod p),\)这个数也不一定是质数
那么就需要进行二次检验
若满足\(x^2=1(\mod p)\)的解为\(x=±1(\mod p)\)
具体流程\(:\)
\(p\)是奇数,那么\(p-1\)是偶数,随机选取底数\(a\)
\(a^{p-1}=1\),然后\(d=\frac{(p-1)}{2}\),相当于对\(a\)开根号继续判断
最后是奇数时候只需判断是否\(a^d\neq ±1(\mod p)\),相当于求解上一步的根就好了
那么关于\(Pollard-Rho\)算法
基本过程\(:\)
随机数,两两做差,判断是否成环,之后判断即可
#define Eternal_Battle ZXK
#include<bits/stdc++.h>
#define int long long
using namespace std;
mt19937_64 rd(random_device{}());
int T,in;
int MO(int x,int mod)
{
if(x<mod) return x;
return x-mod;
}
int my_pow(int a,int b,int mod)
{
int res=1;
while(b)
{
if(b&1)
{
res=((__int128_t)res*a)%mod;
}
a=(__int128_t)a*a%mod;
b>>=1;
}
return res;
}
bool test(int x,int r,int t,int mod)
{
x=my_pow(x,r,mod);
if(x==1||x==mod-1) return false;
for(int i=1;i<t;i++)
{
x=(__int128_t)x*x%mod;
if(x==mod-1) return false;
}
return true;
}
bool mlrb(int x)
{
if(x<2) return false;
int t=0,r=(x-1);
while(r%2==0) r>>=1,t++;
for(int i:{2,3,5,7,11,13,17,19,23,29,31,37})
{
if(x==i) return true;
if(test(i,r,t,x)) return false;
}
return true;
}
int gcd(int a,int b)
{
if(!a) return b;
if(!b) return a;
int t=__builtin_ctzll(a|b);
a>>=__builtin_ctzll(a);
do
{
b>>=__builtin_ctzll(b);
if(a>b){long long t=b;b=a,a=t;}
b-=a;
}
while(b);
return a<<t;
}
int Getp(int x)
{
if(x==1) return x;
if(x&1^1) return 2;
int a=(uniform_int_distribution<long long>(2,x-1))(rd),b=a;
int c=(uniform_int_distribution<long long>(1,x-1))(rd),d=1;
while(d==1)
{
a=MO((int)((__int128_t)a*a%x)+c,x);
b=MO((int)((__int128_t)b*b%x)+c,x);
b=MO((int)((__int128_t)b*b%x)+c,x);
d=gcd(abs(a-b),x);
if(d==x) return Getp(x);
}
return d;
}
vector<int> Getys(int x)
{
vector<int>ys;
queue<int>q;
q.push(x);
while(!q.empty())
{
int now=q.front();
q.pop();
if(mlrb(now)) ys.push_back(now);
else
{
int y=Getp(now);
q.push(y);
q.push(now/y);
}
}
return ys;
}
signed main()
{
scanf("%lld",&T);
while(T--)
{
scanf("%lld",&in);
vector<int>ys=Getys(in);
if(ys.size()==1) puts("Prime");
else
{
int Max=0;
sort(ys.begin(),ys.end());
cout<<ys[ys.size()-1]<<"\n";
}
}
}