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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章