Pollard-Rho
\(code:\)
ll pri[12]={2,3,5,7,11,13,17,19};
ll mul(ll x,ll y,ll mod)
{
ll c=(long double)x*y/mod+0.5;
c=x*y-c*mod;
return c<0?c+mod:c;
}
ll qp(ll x,ll y,ll mod)
{
ll ans=1;
while(y)
{
if(y&1) ans=mul(ans,x,mod);
x=mul(x,x,mod);
y>>=1;
}
return ans%mod;
}
bool check(ll x,ll p,ll mod)
{
ll t=qp(x,p,mod);
if(t==mod-1) return true;
if(t==1) return p&1?true:check(x,p/2,mod);
return false;
}
bool Miller_Rabin(ll n)
{
if(n==1) return false;
if(n<=3) return true;
if(!(n&1)) false;
for(int i=0;i<8;++i)
{
if(n==pri[i]) return true;
if(!check(pri[i],n-1,n)) return false;
}
return true;
}
ll gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
}
ll f(ll x,ll y,ll mod)
{
return (mul(x,x,mod)+y)%mod;
}
ll Pollard_Rho(ll x)
{
ll s=0,t=0,c=(ll)1*rand()%(x-1)+1,val=1;
for(ll goal=1;;goal<<=1,s=t,val=1)
{
for(ll step=1;step<=goal;++step)
{
t=f(t,c,x);
val=mul(val,abs(t-s),x);
if(step%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<=fac_max||x<2) return;
if(Miller_Rabin(x))
{
fac_max=max(fac_max,x);
return;
}
ll p=x;
while(p>=x) p=Pollard_Rho(x);
while(x%p==0) x/=p;
fac(x),fac(p);
}