质数检验

快速检验法

费马(Fermat)素性检验

原理

有费马小定理得,若$p$为质数,$(a,p)=1$成立,则
$$
a^{p-1}=1\pmod{p}
$$

算法

取任意正整数,若$(a,p)=1$且$a^{p-1}\neq 1\pmod{p}$则为合数,否则有可能为质数

时间复杂度为:$O(k\log(n))$,$k$为检验的次数

代码实现

def powmod(a,b,mod):
    res=1
    while b>0:
        if(b&1):
            res=res*a%mod
        a=a*a%mod
        b>>=1
    return res
def Fermat(n,a):
    if powmod(a,n-1,n)==1:
        return True
    else:
        return False

限制

费马素性检验存在伪素数的问题

甚至有一类被称为卡米歇尔数可以通过无限次的费马素数检验

所以费马素性检验在实际应用中并不常用,但是下面米勒-拉宾检测是费马检测的强化版

米勒-拉宾(Rabin-Miller)检测

原理

设$N$为奇合数,$N-1=d\cdot 2^s$,$d$为奇数。若$N$满足
$$
a^d=1 \pmod{N}
$$
或者对于某个$r(0\le r<s)$有
$$
a^{d\cdot 2^r}=-1\pmod{N}
$$
则称$N$为强伪素数

RM检测就是基于强伪素数的检测,与费曼检验不同,只要$a$的取值足够的多就能区分质数和伪素数,MR检测的准确率是$1-4^{-k}$

时间复杂度为:$O(k\log^3{n})$

而且如果广义黎曼猜想(GRH)成立那么就可以证明只要$a$枚举到$\in[2,\lfloor 2(\log n)^2 \rfloor]$,都通过RM检测,那么整数$n$一定是一个质数。

时间复杂度为:$O(\log^5{n})$

虽然MR检测是基于随机的检测,但是$n$在一定范围内只要取特定的$a$这就变成一个确定的算法。
$$
\begin{align}
&\text{if }n<1373653&a&=2,3\\
&\text{if }n<9080191&a&=31,73\\
&\text{if }n<4759123141&a&=2,7,61\\
&\text{if }n<2152302898747&a&=2,3,5,7,11
\end{align}
$$

算法

代码实现

def Rabin_Miller(n,a):
    d=n-1
    s=0
    while d&1==0:
        d>>=1
        s+=1
    for i in a:
        x=powmod(i,d,n)
        if x==1 :
            continue
        for j in range(s):
            if x==n-1:
                x=0
                break
            x=x*x%n
        if x:
            return False
    return True

卢卡斯序列

原理

在斐波那契数列中,若$n$为质数,则$n|F_{n-(5|n)}$。$(a|p)$代表勒让德符号。

卢卡斯序列是斐波那契数列的二次扩域
$$
U_0=0,U_1=1,U_i=PU_{i-1}-QU_{i-2}
$$

代码

def mul(a,b,mod):
    res=[[0,0],[0,0]]
    for i in range(2):
        for j in range(2):
            for k in range(2):
                res[i][j]+=a[i][k]*b[k][j]
            res[i][j]%=mod
    return res
def powmodm(a,b,mod):
    res=[[1,0],[0,1]]
    while b>0:
        if b&1:
            res=mul(res,a,mod)
        a=mul(a,a,mod)
        b>>=1
    return res
def Lucas(n,p,q):
    a=[[p,-q],[1,0]]
    d=p*p-4*q
    dn=powmod(d,(n-1)//2,n)
    if dn==n-1:
        dn=-1
    a=powmodm(a,n-dn-1,n)
    if a[0][0]==0:
        return True
    else:
        return False

Baillie-PSW Test

原理

这个是米勒-拉宾检测和卢卡斯检测的组合。

基于的原理是强卢卡斯伪素数和强米勒罗宾伪素数几乎没有重合。

该算法已知在$2^{64}$范围正确性是得到验证的。

代码

def Baillie_PSW(n):
    if n==1:
        return False
    if not Rabin_Miller(n,[2]):
        return False
    p=1
    q=0
    i=5
    while q==0:
        if powmod(i,(n-1)//2,n)==n-1:
            q=(1-i)//4
        i=-i+2 if i<0 else -i-2
    return Lucas(n,p,q)

参考资料

https://primes.utm.edu/prove/index.html

EricXia

EricXia

喜欢睡觉,热爱钻研各种问题。