Miller Rabin

概要

一种随机化判定质数方法。

根据执行次数不断增加,其正确率可以快速增长,以达到我们想要的目的。


前置知识

二次探测定理

对于质数 \(p\),若有 \(a^2\equiv 1\pmod p\),那么 \(a\equiv \pm 1\pmod p\)

证明:

\[a^2-1\equiv 0\pmod p \]

\[(a+1)(a-1)\equiv 0\pmod p \]

因为 \(p\) 是质数,由唯一分解可得:

\[a\equiv \pm 1 \]


算法流程

\(p-1\) 拆分成 \(2^k\times t\) 的形式,然后 随机 rand 一个 \(a\),计算出 \(a^t\)

每次比较 \(a^{2^i\times t}\pmod p\)\(a^{2^{i+1}\times t}\pmod p,i\in[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;}

posted @ 2020-12-18 22:32  zjjws  阅读(107)  评论(0编辑  收藏  举报