Miller-Rabin素数检测算法

今天看了一下Miller-Rabin素数检测的算法,总结了一下,希望这篇博客对你们有帮助。

 

先说几个理论基础:

1. 费马小定理:假如p是质数,a是整数,且a、p互质,那么a的(p-1)次方除以p的余数恒等于1,即:a^(p-1)≡1(mod p).

但是反过来却不一定成立,就是说,如果a、p互质,且a^(p-1)≡1(mod p),不能推出p是质数,比如Carmichael数。

2. 二次探测定理:如果p是一个素数,0

3. 模运算的规则:(a*b)%n=(a%n * b%n)%n

4. 快速积取模、快速幂取模:可以看看我之前写的一篇博客简单快速的算法

 

然后是算法的过程:

对于要判断的数n

1.先判断是不是2,是的话就返回true。

2.判断是不是小于2的,或合数,是的话就返回false。

3.令n-1=u*2^t,求出u,t,其中u是奇数。

4.随机取一个a,且1

/*根据费马小定理,如果a^(n-1)≡1(mod p)那么n就极有可能是素数,如果等式不成立,那肯定不是素数了

因为n-1=u*2^t,所以a^(n-1)=a^(u*2^t)=(a^u)^(2^t)。*/

5.所以我们令x=(a^u)%n

6.然后是t次循环,每次循环都让y=(x*x)%n,x=y,这样t次循环之后x=a^(u*2^t)=a^(n-1)了

7.因为循环的时候y=(x*x)%n,且x肯定是小于n的,正好可以用二次探测定理,

如果(x^2)%n==1,也就是y等于1的时候,假如n是素数,那么x==1||x==n-1,如果x!=1&&x!=n-1,那么n肯定不是素数了,返回false。

8.运行到这里的时候x=a^(n-1),根据费马小定理,x!=1的话,肯定不是素数了,返回false

9.因为Miller-Rabin得到的结果的正确率为 75%,所以要多次循环步骤4~8来提高正确率

10.循环多次之后还没返回,那么n肯定是素数了,返回true

 

下面是模板:

# include 
# include 
  typedef long long ll;
  ll ModMul(ll a,ll b,ll n)//快速积取模 a*b%n
  {
      ll ans=0;
      while(b)
      {
          if(b&1)
            ans=(ans+a)%n;
          a=(a+a)%n;
          b>>=1;
      }
      return ans;
  }
  ll ModExp(ll a,ll b,ll n)//快速幂取模 a^b%n
  {
      ll ans=1;
      while(b)
      {
          if(b&1)
            ans=ModMul(ans,a,n);
          a=ModMul(a,a,n);
          b>>=1;
      }
      return ans;
  }
  bool miller_rabin(ll n)//Miller-Rabin素数检测算法
  {
      ll i,j,a,x,y,t,u,s=10;
      if(n==2)
        return true;
      if(n<2||!(n&1))
        return false;
      for(t=0,u=n-1;!(u&1);t++,u>>=1);//n-1=u*2^t
      for(i=0;i

HDU 2138 是一道模板题,你们可以练习一下

你可能感兴趣的:(数论)