概要
一种随机化判定质数方法。
根据执行次数不断增加,其正确率可以快速增长,以达到我们想要的目的。
前置知识
二次探测定理
对于质数 (p),若有 (a^2equiv 1pmod p),那么 (aequiv pm 1pmod p)。
证明:
[a^2-1equiv 0pmod p
]
[(a+1)(a-1)equiv 0pmod p
]
因为 (p) 是质数,由唯一分解可得:
[aequiv pm 1
]
算法流程
将 (p-1) 拆分成 (2^k imes t) 的形式,然后 随机 rand 一个 (a),计算出 (a^t)。
每次比较 (a^{2^i imes t}pmod p) 和 (a^{2^{i+1} imes t}pmod p,iin[0,k)) 是否符合前文的二次探测定理。
若出现了一项不符合,即可判定 (p) 为合数。
那么对于当前 rand 出来的这个 (a),有 一定的概率 可以判断出来 (p) 是合数(如果是的话)。
经过一次 (p) 不是质数却未被判出的概率似乎最大为 (frac{1}{4}),具体的我也算不来。
那么做个七八次就好了,非常的稳妥。
可以用 (2,3,5,7,11,13,17,19) 这几个质数作为 (a),也可以 rand 几个质数,看个人习惯。
代码实现
主要是调用的函数部分。
bool pri[20];
vector<int>prime;
inline void init()
{
for(int i=2;i<20;i++){if(!pri[i])prime.push_back(i);for(auto j:prime){int now=i*j;if(now>=20)break;pri[now]=true;if(i%j==0)break;}}
pri[1]=true;srand(time(0));return;
}
inline bool Miller_Robin(LL n,int a)
{
LL t=n-1,lst;int k=0;for(;!(t&1);t>>=1)k++;lst=t=ksm(a,t,n);
for(int i=1;i<=k;i++){t=prpr(t,t,n);if(t==1&&lst!=1&&lst!=n-1)return false;lst=t;}return lst==1;
}
inline bool ifprime(LL n){if(n<20)return !pri[n];for(auto j:prime)if(!Miller_Robin(n,j))return false;return true;}