用费马小定理进行素数判定
1、利用费马小定理
对于素数 p 和与其互质的 a,存在 a p − 1 ≡ 1 ( m o d p ) {a}^{p-1}\equiv 1\ (mod\ \ p) ap−1≡1 (mod p)
那么,如果选取 a,小于 p,如果符合上述公式,这个 p 是不是素数?
这个不可以,比如341,这种数被称为费马伪素数。
2、随机选取
如果这个 a 是随机选取,并且选取几个去验证,是否可以?
也是不可以,比如 561,这种数被称为卡迈克尔数,在 [ 2 , p − 1 ] [2,\, p-1] [2,p−1] 范围内都满足上述公式。
3、总结
存在m,a
m 是奇数
2 < = a < = m − 2 2<=a<=m-2 2<=a<=m−2
g c d ( a , m ) = 1 gcd(a,\, m)\, =\, 1 gcd(a,m)=1
a m − 1 ≡ 1 ( m o d m ) {a}^{m-1}\equiv 1\ (mod\ \ m) am−1≡1 (mod m)
那么 m 至少有 1/2 的概率是素数
二次探测定理
1、内容
存在 p,x
p 是素数
x 2 ≡ 1 ( m o d p ) {x}^{2}\equiv 1\, (mod\, \, p) x2≡1(modp)
x < p
那么
x = 1
x = p - 1
2、证明
x 2 ≡ 1 ( m o d p ) {x}^{2}\equiv 1\, (mod\, \, p) x2≡1(modp)
x 2 − 1 ≡ 0 ( m o d p ) {x}^{2}-1\equiv 0\, (mod\, \, p) x2−1≡0(modp)
( x + 1 ) ( x − 1 ) ≡ 0 ( m o d p ) (x+1)(x-1)\equiv 0\, (mod\, \, p) (x+1)(x−1)≡0(modp)
即 p ∣ ( x − 1 ) ( x + 1 ) p|(x-1)(x+1) p∣(x−1)(x+1)
Miller-Rabin素数判定
时间复杂度
按照我后面给的代码,应该是 O ( k ( l o g 2 n + l o g n ) ) O(k({log}^{2}n + {log}n)) O(k(log2n+logn))
k 为选取基数 x 的次数,log 是在底数为 2 的意义上。
在 2 63 {2}^{63} 263 的数据范围,复杂度降到了 63 2 {63}^{2} 632。
备注: 2 63 {2}^{63} 263 已经要开 unsigned long long 了。
思路
Fermat素数判定和二次探测定理的结合。
对于待检验数 p,随意选取基数 x:
x、p 符合费马小定理
对于 x p {x}^{p} xp 的开方,只有两种结果:1 或 p - 1
对于奇素数,对 x p {x}^{p} xp 不断开方,要么一直是 1 ( m o d p ) 1\, (mod\, \, p) 1(modp),要么出现一个 p - 1 之后都是 1。
(本质而言,p - 1 在模 p 的情况下就是 -1,1 的开方即为 ± 1 \pm 1 ±1)
代码
inline ll quick_multi(ull x, ull y, ull p) // O(1)快速乘
{
return (x * y - (ull)((lb) x / p * y) * p + p) % p;
}
ll quick_pow(ll x, ll y, ll p) //O(logn)快速幂
{
ll sum = 1;
x%= p;
while (y)
{
if (y & 1) sum = quick_multi(sum, x, p);
x = quick_multi(x, x, p);
y>>= 1;
}
return sum;
}
inline bool mr(ll x, ll p) // mille rabin判质数
{
if (quick_pow(x, p - 1, p) != 1) return 0; //费马小定理,快速幂
ll y = p - 1, z;
while (!(y & 1)) //二次探测
{
y >>= 1;
z = quick_pow(x, y, p);
if (z != 1 && z != p - 1) return 0;
if (z == p - 1) return 1;
}
return 1;
}
inline bool prime(ll x)
{
if (x < 2) return 0; // mille rabin判质数
if (x == 2 || x == 3 || x == 5 || x == 7 || x == 43) return 1;
return mr(2, x) && mr(3, x) && mr(5, x) && mr(7, x) && mr(43, x);
}