1 #include<iostream> //该程序为哥德巴赫猜(想输出所有的组合)
2 #include<cmath>
3 #include<cstdlib>
4 #include<ctime>
5 #include<cstdio>
6
7 using namespace std;
8
9 typedef unsigned long long ull;
10 typedef unsigned long long LL;
11
12 LL prime[6] = {2, 3, 5, 233, 331};
13 LL qmul(LL x, LL y, LL mod) { // 乘法防止溢出, 如果p * p不爆LL的话可以直接乘; O(1)乘法或者转化成二进制加法
14 //快速乘法取模算法
15
16 return (x * y - (long long)(x / (long double)mod * y + 1e-3) *mod + mod) % mod;
17 /*
18 LL ret = 0;
19 while(y) {
20 if(y & 1)
21 ret = (ret + x) % mod;
22 x = x * 2 % mod;
23 y >>= 1;
24 }
25 return ret;
26 */
27 }
28
29 LL qpow(LL a, LL n, LL mod) {
30 LL ret = 1;
31 while(n) {
32 if(n & 1) ret = qmul(ret, a, mod);
33 a = qmul(a, a, mod);
34 n >>= 1;//n=n/2二进制乘除法
35 }
36 return ret;
37 }
38
39
40 bool Miller_Rabin(LL p) {
41 if(p < 2) return 0;
42 if(p != 2 && p % 2 == 0) return 0;
43 LL s = p - 1;
44 while(! (s & 1)) s >>= 1;//排除掉偶数
45 for(int i = 0; i < 5; ++i) {
46 if(p == prime[i]) return 1;
47 LL t = s, m = qpow(prime[i], s, p);
48 //二次探测定理卡米歇尔数保证该数为素数
49 //卡米歇尔数若一个数为合数当0<x<p,则方程x^p≡a(mod p)
50 //二次探测定理如果p是一个素数,0<x<p,则方程x^2≡1(mod p)的解为x=1,p-1
51 while(t != p - 1 && m != 1 && m != p - 1) {
52 m = qmul(m, m, p);
53 t <<= 1;
54 }
55 if(m != p - 1 && !(t & 1)) return 0;//不是奇数且m!=p-1
56 }
57 return 1;
58 }