Miller-Rabin&Pollard-Rho

Miller-Rabin&Pollard-Rho

Miller-Rabin

二次探测定理

\(x^2 \equiv 1 \pmod{p}\Leftrightarrow x \equiv 1 \pmod{p} ~\text{or}~x \equiv -1 \pmod{p}\)

证明我不会

步骤

首先用费马小定理去除一般合数

然后对\(p^{x-1}\equiv 1\pmod x\)

\(x-1\)为偶数

检验\(p^{\frac{x-1}{2}}\pmod x\):

  • \(\ne 1,\ne x-1\) 为合数退出
  • \(= 1\)继续
  • \(= x-1\)认为是素数
inline char Check(re ll x,re ll p){
    if(qpow(p%x,x-1,x)^1)return 0;
    re ll k=x-1,t;
    while(!(k&1)){
        if((t=qpow(p%x,k>>=1,x))^1&&t^(x-1))return 0;
        if(!(t^(x-1)))return 1;
    }
    return 1;
}
inline char Miller_Rabin(re ll x){
    re ll i;
    if(x==1)return 0;
    for(i=1;i<=*pri;++i){if(!(x^pri[i]))return 1;if(!(x%pri[i])||!Check(x,pri[i]))return 0;}
    return 1;
}

Pollard-Rho

思想

随机抽样一些数,其中有两者之差与待测数不互质概率会随抽样个数增大飞快增大

不靠谱的说法,期望抽样次数为\(O(\sqrt[4]n)\)

流程

首先我们需要一个伪随机数列来生成样本常用\(f(x)=(x^2+c)\mod N\)(曼德勃罗集)

为什么不选取随机数列(我指系统的),因为随机数列循环节太长

而这个伪随机数列始终会进入一个循环恰似\(\rho\)

然后考虑每次都求\(\gcd\)反而让时间退化

考虑倍增,把一段里的积累计起来(反正你又不需要知道是那个差不互质)

现在我们要走\(2^k\)

那么每到\(127\)步或整个倍增段走完时判定一下累乘的积是否与\(x\)不互质即可

至于为什么是\(127\)……

inline ll Pollard_rho(re ll x,re ll c){
    re ll goal,i,st=0,now=0,pro=1ll,d;if(c<=0)c=1ll*rand()%(x-1)+1;
    for(goal=1;;goal<<=1,st=now,pro=1ll){
        for(i=1;i<=goal;++i){
            now=(qmul(now,now,x)+c)%x;pro=qmul(pro,Abs(now-st),x);
            if(!(i%127)){d=qgcd(pro,x);if(d^1)return d;}
        }
        d=qgcd(pro,x);if(d^1)return d;
    }
}
inline void Findfac(re ll n,re int k){
    if(!(n^1)||n<=ans)return ;if(Miller_Rabin(n))return void(ans=max(ans,n));
    re ll p=n;while((p=Pollard_rho(n,k--))==n);while(!(n%p))n/=p;Findfac(n,k),Findfac(p,k);
}

卡常

可以写一个很牛逼的二进制\(gcd\)

不知道哪里抄来的

#define mytz __builtin_ctzll
inline ll qgcd(ll a, ll b){
    if(!a) return b;
    if(!b) return a;
    register int t = mytz(a|b) ;
    a >>= mytz(a) ;
    do{
        b >>= mytz(b) ;
        if(a>b){ll t=b;b=a,a=t;}
        b-=a;
    }while(b);
    return a<<t;
}

猜你喜欢

转载自www.cnblogs.com/66t6/p/12238518.html
今日推荐