Miller_Rabin 素数测试

费马定理的逆定理几乎可以用来判断一个数是否为素数,但是有一些数是判断不出来的,因此,Miller_Rabin测试方法对费马的测试过程做了改进,克服其存在的问题。

推理过程如下(摘自维基百科):

摘自另一篇博文(手动滑稽):

原理明白了,就直接上代码了(KuangBin大神的板子):

代码思路是,

  • Miller_Rabin()函数随机选取 s 个a,a用做“基底”
  • check() 函数是用来判断x是否等于1,也就是判断a是否是n的凭证。
  • Mul_mod()函数是 快速乘 ,求 a^t % n 之后的值是否为正负一,因为两个数直接乘的话会很大,可能会爆Long Long, 因此用快速乘边乘边mod。
  • pow_mod()函数是 快速幂 ,在刚开始第一次判断 a^(n-1) % n 时会用到。 
 1 /* *************************************************
 2 * Miller_Rabin 算法进行素数测试
 3 * 速度快可以判断一个 < 2^63 的数是不是素数
 4 *
 5 **************************************************/
 6 const int S = 8; //随机算法判定次数一般 8 ∼ 10 就够了
 7 // 计算 ret = (a*b)%c
 8 //a,b,c < 2^63
 9 long long mult_mod(long long a,long long b,long long c)
10 {
11     a %= c;
12     b %= c;
13     long long ret = 0;
14     long long tmp = a;
15     while(b)
16     {
17         if(b & 1)
18         {
19             ret += tmp;
20             if(ret > c)ret -= c;//直接取模慢很多
21         }
22         tmp <<= 1;
23         if(tmp > c)tmp -= c;
24         b >>= 1;
25     }
26     return ret;
27 }
28 // 计算 ret = (a^n)%mod
29 long long pow_mod(long long a,long long n,long long mod)
30 {
31     long long ret = 1;
32     long long temp = a%mod;
33     while(n)
34     {
35         if(n & 1)ret = mult_mod(ret,temp,mod);
36         temp = mult_mod(temp,temp,mod);
37         n >>= 1;
38     }
39     return ret;
40 }
41 // 通过 a^(n − 1)=1(mod n)来判断 n 是不是素数
42 // n − 1 = x ∗ 2 t 中间使用二次判断
43 // 是合数返回 true, 不一定是合数返回 false
44 bool check(long long a,long long n,long long x,long long t)
45 {
46     long long ret = pow_mod(a,x,n);
47     long long last = ret;
48     for(int i = 1; i <= t; i++)
49     {
50         ret = mult_mod(ret,ret,n);
51         if(ret == 1 && last != 1 && last != n - 1)return true;//合数
52         last = ret;
53     }
54     if(ret != 1)return true;
55     else return false;
56 }
57 //**************************************************
58 // Miller_Rabin 算法
59 // 是素数返回 true,(可能是伪素数)
60 // 不是素数返回 false
61 //**************************************************
62 bool Miller_Rabin(long long n)
63 {
64     if( n < 2)return false;
65     if( n == 2)return true;
66     if( (n&1) == 0)return false;//偶数
67     long long x = n - 1;
68     long long t = 0;
69     while( (x&1)==0 )
70     {
71         x >>= 1;
72         t++;
73     }
74     srand(time(NULL));/* *************** */
75     for(int i = 0; i < S; i++)
76     {
77         long long a = rand()%(n - 1) + 1;
78         if( check(a,n,x,t) )
79             return false;
80     }
81     return true;
82 }
View Code

猜你喜欢

转载自www.cnblogs.com/daybreaking/p/9853433.html