MillerRabin素性检测

Miller Rabin素性检验是一种素数判定的法则,由CMU的教授Miller首次提出,并由希大的Rabin教授作出修改,能够在O(k*logn^3)的时间内算出一个数是不是素数,但是有一定的错误概率

根据检测的次数n,可以把错误概率降低到  (1/4)^n  实际上比这个还要小

在int范围内,选取 {2,7,61} 三个数作为底数可以保证100%正确。

在long long范围内,选取 {2,325,9375,28178,450775,9780504,1795265022} 七个数作为底数可保证100%正确。

依据原理:

  1. 费马小定理
  2. 有限域 Fp 上对1开方只能得到1或-1,n为合数时,对1开方可以开出其他的结果

原理理解:

        

由Fermat检测得 a^{p-1}≡1(mod p)。 

将其拆分为 a^{(\frac{p-1}{2})^{2}} ≡1(mod p)。用二次检测定理来判断.

a ^{\frac{p-1}{2}}≡1(mod p) 或者 a ^{\frac{p-1}{2}}≡-1(mod p),同样的我们可以递推下去到a ^{\frac{p-1}{4}}a ^{\frac{p-1}{8}}

也就是说,我们可以将奇数n表示成n-1=2^{s}*t,对a^{t}a^{t*2}a^{t*2^{2}}... 这一系列数进行检验,这一系列数进行检验,他们的解要么全是1,要么出现 −1 后全是1(之前不能有1),否则就不是素数。当然,要注意 −1 不能出现在最后一个数,否则就连费马小定理都不满足了。

具体计算过程:

总结一下,该检验的思路是:

1)先特判筛掉3以下的数与偶数。

2)将待检验数 n, n−1 化为2^{s}*t

3)选取多个底数,分别对a^{t}a^{t*2}a^{t*2^{2}}… 进行检验,判断其解是否全为1,或在非最后一个数的情况下出现 p−1,然后之后全是1 。

4)如果都满足,我们就认为这个数是素数。

样例代码:

eg1.

bool MRtest(ll n)//Miller Rabin Test
{
    if(n<3||n%2==0) return n==2;//特判
    ll u=n-1,t=0;
    while(u%2==0) u/=2,++t;
    ll ud[]={2,325,9375,28178,450775,9780504,1795265022};
    for(ll a:ud)
    {
        ll v=qpow(a,u,n);
        if(v==1||v==n-1) continue; // 第一步就得到了1 or p-1 可以直接跳过后面的循环
        for(int j=1;j<=t;j++)
        {
            v=qmul(v,v,n);
            if(v==n-1&&j!=t){v=1;break;}//出现一个n-1,后面都是1,直接跳出
            if(v==1) return 0;//这里代表前面没有出现n-1这个解,二次检验失败
        }
        if(v!=1) return 0;//Fermat检验
    }
    return 1;
}

eg2.

bool Miller_Rabin(ll n)
{
	int m = n-1;
	int t = 0;
 
	if (n==2)
	{
 		return true;
	}
	else if (n<2 || !(n&1))
	{
 		return false;
	}
 
 	//求出n-1 = m*2^t的m和t。
	while (!(m&1))
	{
		m>>=1;
		t++;
	}
 
	for (int i=0; i<20; i++)
	{    
		//随机数a
		ll a = rand()%(n-1) + 1;
		// 计算a^m
		ll x = qul_pow(a, m, n), y;
  		
		for (int j=0; j<t; j++)
		{
			y = qul_mul(x, x, n);  //进行(x*x)%n操作。
   			
   			//不满足二次探测定理,也就是y得1了但是x并不等于1或者n-1,那么n就一定不是质数。
			if (y==1 && x!=1 && x!=n-1)
			{
 				return false;
			}
   
			x = y;
		}
  		//上面循环跑完了,如果最后x都不等于1,那么一定是一个合数了。
		if (x!=1)
		{
			return false;
		}
	}
 
	return true;
}

 eg1和eg2是主流的两种代码, 其实都是一样的.

参考资料:

【朝夕的ACM笔记】数论-Miller Rabin素数判定 - 知乎 (zhihu.com)

算法学习笔记(48): 米勒-拉宾素性检验 - 知乎 (zhihu.com)

Miller-Rabin算法-CSDN博客

  • 21
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值