Miller_Rabin 简要版
简介:通俗易懂版本。
1.很 naive 的检验——费马小定理的逆定理
我们知道 nnn 为质数的时候 an−1≡1(modn)a^{n-1}\equiv1\pmod{n}an−1≡1(modn) 成立。
所以不妨就随机几个 aaa 为底然后判断一下费马小定理是否成立即可。
mt19937 Rand(time(0));
LL mul(LL a,LL b,LL p){
return (__int128)a*b%p;
}LL pow(LL a,LL b,LL p){
LL ans=1;
for(;b;b>>=1){
if(b&1)ans=mul(ans,a,p);
a=mul(a,a,p);}
return ans;
}bool pd(LL x){
if(x<=2)return x==2;
LL a;
for(I i=1;i<=10;++i){
a=Rand()%(x-2)+2;
if(pow(a,x-1,x)!=1)
return 0;
}return 1;
}
果不其然,WA 成狗了,33分。(LOJ#147 素数判定)
为什么?因为可以构造 卡迈克尔 数来卡掉这个玩意,能通过所有的检验但是它是一个和数。
所以我们要结合另外的方法。
2.大神出场——二次探测
此处应该有掌声
先来介绍一个定理,如果 ppp 为奇素数,那么 对于 x2≡1(modp)x^2\equiv1\pmod px2≡1(modp) 的方程,有两个平凡平方根:x=1x=1x=1 或者 x=p−1x=p-1x=p−1 。
(为什么不为偶素数,即为2呢?因为 xxx 只有一个解,即 111 。)
移项,x2−1≡0(modp)x^2-1\equiv0\pmod px2−1≡0(modp)
所以 (x+1)(x−1)≡0(modp)(x+1)(x-1)\equiv0\pmod p(x+1)(x−1)≡0(modp)。所以 x=1x=1x=1 或者 x=p−1x=p-1x=p−1 。
3.Miller_Rabin 算法实现
我们不是在 (1) 中处理出来 an−1a^{n-1}an−1 了吗?
那么我们就继续处理它:把 n−1n-1n−1 分解成 u×2tu\times 2^tu×2t 的形式(这个比较简单哈)。显然 n−1n-1n−1 为偶数。
我们回想一下上面的二次探测有什么用呢?奇素数只有两个平凡平方根。
而有非平凡平方根,这说明了什么?
再具体代入一对解,x2≡y2≡1(modp)x^2\equiv y^2\equiv1\pmod px2≡y2≡1(modp) 则 (x+y)(x−y)≡0(modp)(x+y)(x-y)\equiv0\pmod p(x+y)(x−y)≡0(modp) 。
显然, x−y≤px-y\le px−y≤p 。所以如果不是非平凡平方根的话,这个 ppp 必然会被分解成另外的形式!
那么 ppp 就不是一个素数了。
所以,如果 x2≡1(modn)x^2\equiv 1\pmod nx2≡1(modn) 而 x≠1x\ne 1x=1 或者 n−1n-1n−1 的话 xxx 就是一个非平凡平方根。ppp 是过不了检验的。
实现的时候,先算出 aua^uau 的值 vvv ;然后不断平方 ttt 次。不断平方,aua^uau 变成 a2ua^{2u}a2u 一直变成 a2tua^{2^tu}a2tu 即 an−1a^{n-1}an−1 。
在不断平方的过程中,先判断 vvv 和 ppp 的关系,然后再平方。
bool pd(LL n){
if(n<3||n%2==0)return n==2;
LL u=n-1,t=0;
while(u%2==0)u>>=1,++t;
for(I i=1,j;i<=10;++i){
LL a=Rand()%(n-2)+2,v=pow(a,u,n);
if(v==1)continue;
for(j=1;j<=t;++j){
if(v==n-1)break;
v=mul(v,v,n);
}
if(j>t)return 0;
}return 1;
}
本文介绍了Miller-Rabin素数判定算法,包括其基于费马小定理的朴素检验、为何失败以及如何通过二次探测改进。详细阐述了算法的实现过程,并讨论了算法的应用。通过多次随机选取基数进行测试,该算法能有效提高素数判定的准确性。
11万+

被折叠的 条评论
为什么被折叠?



