MillerRabin素性判定

随机的素性判定算法,但判定次数更多正确率越大。

前置知识:

  • 费马小定理

\(a^{p-1}\equiv 1 \mod p\),p为任意质数,a为任意整数

并且逆否命题成立,即:对于任意整数\(a<pa<p\),不满足\(a^{p−1}\equiv 1 \mod p\),则\(p\)为合数。

  • 二次探测定理

如果有\(0< x < p\)并且\(p\)为素数,并且有方程\(x^2\equiv 1 \mod p\),则方程有两解\(x_1=1,x_2=p-1\)

\([2,p-1]\)中随机取\(a\),在\(s\)次探测以后判为不是合数后则为质数。

判定办法:

\(p-1=2^{t}u\),取\(x[0]=a^u \mod p\)\(x[0]\)平方了\(t\)次以后则为\((a^u)^{2^t} \mod p\),即\(a^{2^tu} \mod p\)

如果不为\(1\),那么该数不是质数;如果为\(1\)但解不是\(1\)\(p-1\)则该数不是质数。

判定\(s\)次即可,\(s\)通常取\(20\)等。

复杂度为\(O(slog_3n)\)

值得注意的是数字较大的时候要使用慢速乘。

ll range(int l,int r) {
  return abs(rand())%(r-l+1)+l;
}

// 当x很大时 long long会乘爆,需要使用慢速乘
ll SlowMul(ll a,ll b,ll mo) {
  ll ret=0;
  while(b) {
    if(b&1) ret=(ret+a)%mo;
    a=(a+a)%mo;
    b>>=1;
  }
  return ret;
}

ll QuickPow(ll x,ll k,ll mo) {
  ll ret=1ll;
  while(k) {
    if(k&1) ret=ret*x%mo;
    x=x*x%mo;
    k>>=1;
  }
  return ret;
}

bool MillerRabin(ll x) {
  if(x==2) return true;
  int t=0;
  ll u=x-1;
  while(!(u&1)) {
    t++;
    u>>=1;
  }

  int s=20;
  ll now,pre;
  while(s--) {
    ll a=range(1,x-1);
    now=QuickPow(a,u,x);
    for(int z=0;z<t;z++) {
      pre=now;
      now=now*now%x;
      if(now==1 && pre!=1 && pre!=x-1) return false;
    }
    if(now!=1) return false;
  }
  return true;
}

猜你喜欢

转载自www.cnblogs.com/darkroome/p/9210449.html