Miller-Rabin算法
前置知识
-
费马小定理
若\(p\)为素数, \(a\)为正整数,且\(gcd(a,p) = 1\),则\(a^{p-1}\equiv 1(mod p)\).-
证明:首先证明三个小性质
因为\(p\)为素数,所以\(gcd(i,p)=1,1\le i \le p-1,i为整数\), 则可推出:\[gcd((p-1)!,p)=1 \]又因为\(gcd(a,p)=1\), 所以 $$gcd(i \ast a,p)=1,1\le i\le p-1$$
设 \(a = b*q+r,1\le r< p\),则\(gcd(i*r,p)=1\).
假设存在两个不同的\(i\),\(c和d\),满足\(c*r\equiv d*r(\mod p) (c< d)\)
那么\((d-c)*r\equiv 0(\mod p)\) ,即 \(p|(d-c)*r\).
又因为\(1\le d-c < p\), 这与\(gcd(i*r,p)=1\)矛盾.
所以\(i*r,1\le i\le p-1\)没有任何两个不同的i使得这两个数模\(p\)同余。
所以 $$ i\ast a不存在两个不同的i使得这两个数能在模p的意义下同余$$接下来我们就可以证明费马小定理了。
我们从上面的推断可以得出,\(\prod_{i=1}^{p-1} i\ast a \equiv \prod_{i=1}^{p-1} i (\mod p)\)即 $$ (p-1)! \ast a^{p-1} \equiv (p-1)! (\mod p) $$
即 $$ a^{p-1} \equiv 1 (\mod p)$$
-
-
二次探测定理
若\(p\)为奇素数且\(x^2 \equiv 1(\mod p)\), 则\(x\equiv 1(\mod p)\)或\(x \equiv p-1(\mod p)\).
证明:\(x^2 \equiv 1(\mod p)\)
则 \((x-1)(x+1) \equiv 0(\mod p)\)
则 \(x_1 = q_1*p+1,x_2 = q_2*p-1,q_1,q_2为整数\), 显然符合\(x\equiv 1(\mod p)\)或\(x \equiv p-1(\mod p)\)。对于要验证的数\(p\), 我们可以选择一些正整数\(a\),使用费马小定理来测试,若有一个\(a\)不符合那\(p\)就不是素数.
但是这只是必要非充分条件,实际上存在一种强伪素数\(p\),符合:
$$ \forall a<p, a^{p-1}\equiv 1( \mod p) $$
啊 这。 所以不能用费马小定理直接判断素数。
所以我们需要第二次探测。
首先对p使用费马小定理进行判断,若不符合直接判合数。
若\(2|p-1\), 则我们需要判断是否符合\((x^{{p-1}/2})^2\)模\(p\)为1或\(p-1\).
若\((x^{{(p-1)}/2})^2\)模\(p\)值既不是1也不是\(p-1\),则\(p\)是合数.返回false。
若是1,则继续递归。\(k=(p-1) \rightarrow k>>=1 \rightarrow ... ;\) 直到k为奇数。返回true.
若是\(p-1\),则返回true。
通过多取几个x来提高测试的准确率。一般来说取2~23中的所有素数就可满足要求。class MillerRabin { public: Con int P[10] = { 2,3,5,7,11,13,19,61,2333,24251 }; bool check(int x, int p) { if (!(x%p) || Qpow(p%x, x - 1, x) != 1) { return false; } ll k = x - 1, t; while (!(k & 1)) { t = Qpow(p%x, k >>= 1, x); if (t ^ 1 && t ^ (x - 1)) return false; if (!(t ^ (x - 1))) return true; } return true; } bool IsPrime(int x) { if (x < 2) return false; for (Reg int i = 0; i < 10; ++i) { if (!(x^P[i])) return true; if (!check(x, P[i])) return false; } return true; } }MR;

浙公网安备 33010602011771号