51nod1186(Miller-Rabin)

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1186

 

题意:中文题目诶~

 

思路:miller_rabin模板 (详情可参见: http://blog.csdn.net/s031302306/article/details/51606018)

注意这里的 n 为 1e30,需要用字符串处理

 

代码:

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

 

对于long long范围:

 1 #include <stdio.h>
 2 #include <iostream>
 3 #include <cstdlib>
 4 #define ll long long
 5 using namespace std;
 6 
 7 //利用二进制计算a*b%mod
 8 ll multi_mod(ll a, ll b, ll mod){
 9     ll ans = 0LL;
10     a %= mod;
11     while(b){
12         if (b & 1LL) ans = (ans+a)%mod;
13         b >>= 1LL;
14         a = (a+a)%mod;
15     }
16     return ans;
17 }
18 
19 //计算a^b%mod
20 ll power_mod(ll a, ll b, ll mod){
21     ll ans = 1LL;
22     a %= mod;
23     while(b){
24         if(b & 1LL) ans = multi_mod(ans, a, mod);
25         b >>= 1LL;
26         a = multi_mod(a, a, mod);
27     }
28     return ans;
29 }
30 
31 //Miller-Rabin测试,测试n是否为素数
32 bool miller_rabin(ll n, int repeat){
33     if (2LL == n || 3LL == n) return true;
34     if (n%2==0 || n%3==0 || n%5==0) return false;
35 
36     //将n分解为2^s*d
37     ll d = n - 1LL;
38     int s = 0;
39     while(!(d & 1LL)){
40         s++;
41         d >>= 1LL;
42     }
43     // srand((unsigned)time(0));
44     for(int i=0; i<repeat; ++i){//重复repeat次
45         ll a = rand() % (n - 3) + 2;//取一个随机数,[2,n-1)
46         ll x = power_mod(a, d, n);
47         ll y = 0LL;
48         for(int j=0; j<s; ++j){
49             y = multi_mod(x, x, n);
50             if (1LL == y && 1LL != x && n-1LL != x) return false;
51             x = y;
52         }
53         if (1LL != y) return false;
54     }
55     return true;
56 }
57 
58 int main(void){
59     ll n;
60     cin >> n;
61     if(miller_rabin(n, 5)) cout << "Yes" << endl;
62     else cout << "No" << endl;
63     return 0;
64 }
View Code

 

posted @ 2017-05-25 16:13  geloutingyu  阅读(269)  评论(0编辑  收藏  举报