Miller-Rabin素数测试

Posted starry

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Miller-Rabin素数测试相关的知识,希望对你有一定的参考价值。

费尔马小定理:如果p是一个素数,且0<a<p,则a^(p-1)%p=1.利用费尔马小定理,对于给定的整数n,可以设计素数判定算法,

        通过计算d=a^(n-1)%n来判断n的素性,当d!=1时,n肯定不是素数,当d=1时,n   很可能是素数.

 

二次探测定理:如果技术分享是素数,且技术分享,则方程技术分享的解为技术分享技术分享

        利用二次探测定理,可以再利用费尔马小定理计算a^(n-1)%n的过程 中增加对整数n的二次探测,

       一旦发现违背二次探测条件,即得出n不是素数的结论.

 

先贴出long long 范围的代码:

 1 /*
 2 long long 范围的Miller-Rabin素数测试
 3 */
 4 
 5 #include <iostream>
 6 #include <stdio.h>
 7 #include <string.h>
 8 #include <stdlib.h>
 9 #include <time.h>
10 #define ll long long
11 using namespace std;
12 
13 //计算a*b%mod
14 ll mod_mul(ll a, ll b, ll n){
15     ll cnt = 0LL;
16     while(b){
17         if(b&1LL) cnt = (cnt+a)%n;
18         a=(a+a)%n;
19         b >>= 1LL;
20     }
21     return cnt;
22 }
23 //计算a^b%mod
24 ll mod_exp(ll a, ll b, ll n){
25     ll res = 1LL;
26     while(b){
27         if(b&1LL) res = mod_mul(res,a,n);
28         a = mod_mul(a,a,n);
29         b >>= 1LL;
30     }
31     return res;
32 }
33 //Miller-Rabin测试,测试n是否为素数
34 bool Miller_Rabin(ll n, int respat){
35     if(n==2LL || n==3LL || n==5LL || n==7LL || n==11LL) return true;
36     if(n==1 || !(n%2) || !(n%3) || !(n%5) || !(n%7) || !(n%11)) return false;
37     
38     int k = 0;
39     ll d = n-1; //要求x^u%n 不为1一定不是素数
40     
41     while(!(d&1LL)){
42         k++; d >>= 1LL;
43     }
44     srand((ll)time(0));
45     for(int i = 0; i < respat; i ++) {
46         ll a = rand()%(n-2)+2;     //在[2,n)中取整数
47         ll x = mod_exp(a,d,n);
48         ll y = 0LL;
49         for(int j = 0; j < k; j ++){
50             y = mod_mul(x,x,n);
51             if(1LL==y && 1LL!=x && n-1LL!=x)return false; //二次探测定理,这里如果y = 1则x必须等于 1
52                                                           //或n-1,否则可以判断不是素数
53             x = y;
54         }
55         if(1LL != y) return false;     //费马小定理
56     }
57     return true;
58 }
59 int main(){
60     int n;
61     cin>>n;
62     if(Miller_Rabin(n,5))cout << "Yes\n";
63     else cout << "No\n";
64     return 0;
65 }

 

 

当数字达到10^30时,就要用到大数了,贴下模板。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 
  5 #define MAXL 4
  6 #define M10 1000000000
  7 #define Z10 9
  8 
  9 const int zero[MAXL - 1] = {0};
 10 
 11 struct bnum{
 12     int data[MAXL]; //  断成每截9个长度
 13     
 14     //  读取字符串并转存
 15     void read(){
 16         memset(data, 0, sizeof(data));
 17         char buf[32];
 18         scanf("%s", buf);
 19         int len = (int)strlen(buf);
 20         int i = 0, k;
 21         while (len >= Z10){
 22             for (k = len - Z10; k < len; ++k){
 23                 data[i] = data[i] * 10 + buf[k] - 0;
 24             }
 25             ++i;
 26             len -= Z10;
 27         }
 28         if (len > 0){
 29             for (k = 0; k < len; ++k){
 30                 data[i] = data[i] * 10 + buf[k] - 0;
 31             }
 32         }
 33     }
 34     
 35     bool operator == (const bnum &x) {
 36         return memcmp(data, x.data, sizeof(data)) == 0;
 37     }
 38     
 39     bnum & operator = (const int x){
 40         memset(data, 0, sizeof(data));
 41         data[0] = x;
 42         return *this;
 43     }
 44     
 45     bnum operator + (const bnum &x){
 46         int i, carry = 0;
 47         bnum ans;
 48         for (i = 0; i < MAXL; ++i){
 49             ans.data[i] = data[i] + x.data[i] + carry;
 50             carry = ans.data[i] / M10;
 51             ans.data[i] %= M10;
 52         }
 53         return  ans;
 54     }
 55     
 56     bnum operator - (const bnum &x){
 57         int i, carry = 0;
 58         bnum ans;
 59         for (i = 0; i < MAXL; ++i){
 60             ans.data[i] = data[i] - x.data[i] - carry;
 61             if (ans.data[i] < 0){
 62                 ans.data[i] += M10;
 63                 carry = 1;
 64             }
 65             else{
 66                 carry = 0;
 67             }
 68         }
 69         return ans;
 70     }
 71     
 72     //  assume *this < x * 2
 73     bnum operator % (const bnum &x){
 74         int i;
 75         for (i = MAXL - 1; i >= 0; --i){
 76             if (data[i] < x.data[i]){
 77                 return *this;
 78             }
 79             else if (data[i] > x.data[i]){
 80                 break;
 81             }
 82         }
 83         return ((*this) - x);
 84     }
 85     
 86     bnum & div2(){
 87         int  i, carry = 0, tmp;
 88         for (i = MAXL - 1; i >= 0; --i){
 89             tmp = data[i] & 1;
 90             data[i] = (data[i] + carry) >> 1;
 91             carry = tmp * M10;
 92         }
 93         return *this;
 94     }
 95     
 96     bool is_odd(){
 97         return (data[0] & 1) == 1;
 98     }
 99     
100     bool is_zero(){
101         for (int i = 0; i < MAXL; ++i){
102             if (data[i]){
103                 return false;
104             }
105         }
106         return true;
107     }
108 };
109 
110 void mulmod(bnum &a0, bnum &b0, bnum &p, bnum &ans){
111     bnum tmp = a0, b = b0;
112     ans = 0;
113     while (!b.is_zero()){
114         if (b.is_odd()){
115             ans = (ans + tmp) % p;
116         }
117         tmp = (tmp + tmp) % p;
118         b.div2();
119     }
120 }
121 
122 void powmod(bnum &a0, bnum &b0, bnum &p, bnum &ans){
123     bnum tmp = a0, b = b0;
124     ans = 1;
125     while (!b.is_zero()){
126         if (b.is_odd()){
127             mulmod(ans, tmp, p, ans);
128         }
129         mulmod(tmp, tmp, p, tmp);
130         b.div2();
131     }
132 }
133 
134 bool MillerRabinTest(bnum &p, int iter){
135     int  i, small = 0, j, d = 0;
136     for (i = 1; i < MAXL; ++i){
137         if (p.data[i]){
138             break;
139         }
140     }
141     if (i == MAXL){
142         // small integer test
143         if (p.data[0] < 2){
144             return  false;
145         }
146         if (p.data[0] == 2){
147             return  true;
148         }
149         small = 1;
150     }
151     if (!p.is_odd()){
152         return false;   //  even number
153     }
154     bnum a, s, m, one, pd1;
155     one = 1;
156     s = pd1 = p - one;
157     while (!s.is_odd()){
158         s.div2();
159         ++d;
160     }
161     
162     for (i = 0; i < iter; ++i){
163         a = rand();
164         if (small){
165             a.data[0] = a.data[0] % (p.data[0] - 1) + 1;
166         }
167         else{
168             a.data[1] = a.data[0] / M10;
169             a.data[0] %= M10;
170         }
171         if (a == one){
172             continue;
173         }
174         
175         powmod(a, s, p, m);
176         
177         for (j = 0; j < d && !(m == one) && !(m == pd1); ++j){
178             mulmod(m, m, p, m);
179         }
180         if (!(m == pd1) && j > 0){
181             return false;
182         }
183     }
184     return true;
185 }
186 
187 int main(){
188     bnum x;
189     
190     x.read();
191     puts(MillerRabinTest(x, 5) ? "Yes" : "No");
192     
193     return 0;
194 }

 

以上是关于Miller-Rabin素数测试的主要内容,如果未能解决你的问题,请参考以下文章

Miller-Rabin素数测试

Miller-Rabin素数测试

Miller-Rabin素数测试

记一次使用快速幂与Miller-Rabin的大素数生成算法

poj 2429GCD & LCM Inverse (Miller-Rabin素数测试和Pollard_Rho_因数分解)

ACM入门之Miller-Rabin素数测试算法