Miller Rabin 判素算法

本文介绍了在大数范围内如何利用Miller-Rabin算法进行素性检验,详细阐述了费马小定理和二次探测定理,并提供了在OIOI数据范围内确定性判断质数的方法,包括选取特定底数进行多次验证以降低误判概率。
摘要由CSDN通过智能技术生成

引入

给出 t    ( t ≤ 500 ) t~~(t\le500) t  (t500) 个正整数 x    ( x ≤ 2 63 − 1 ) x~~(x\le2^{63}-1) x  (x2631),判断 x x x 是否为质数。


Miller Rabin 素性检验

显然在这个 x x x 的范围下,试除法判断质数是不行的。

M i l l e r   R a b i n \mathbf{Miller\ Rabin} Miller Rabin 素性检验就是一种用来 判断大数是否为质数随机性 算法。
它在计算机科学中的用途是用来判断工业质数 ( ≥ 2 1024 的 质 数 ) (\ge2^{1024}的质数) (21024),在这个范围下它的判断是否正确存在随机性,但是在 O I OI OI 范围下 ( ≤ 2 63 − 1 ) (\le 2^{63}-1) (2631) 确是一种 错误率极低确定性 算法。

在 引入 的问题中,我们可以考虑使用 M i l l e r   R a b i n \mathbf{Miller\ Rabin} Miller Rabin 素性检验来判断质数。
M i l l e r   R a b i n \mathbf{Miller\ Rabin} Miller Rabin 素性检验中,我们要先了解它判断素数的理论基础:

  • 费马素性检验
  • 二次探测定理

费马素性检验

费马小定理:

若 p 是 质 数 , gcd ⁡ ( a , p ) = 1 , 则   a p − 1 ≡ 1 ( m o d p ) 若p是质数,\gcd(a,p)=1,则\ a^{p-1}\equiv1\pmod p pgcd(a,p)=1, ap11(modp)
证明:

考 虑 P = { m 1 , m 2 , m 3 , ⋯   , m p − 1 } , m i < p , 显 然 有 m i ≢ m j ( m o d p ) ∵ gcd ⁡ ( a , p ) = 1 ∴ 对 于 Q = { a ⋅ m 1 , a ⋅ m 2 , a ⋅ m 3 , ⋯   , a ⋅ m p − 1 } , 也 有 a ⋅ m i ≢ a ⋅ m j ( m o d p )   利 用 同 余 式 的 性 质 , 我 们 对 这 两 个 两 两 元 素 之 间 不 同 余 的 集 合 联 利 , 得 ∏ i = 1 p − 1 a ⋅ m i ≡ ∏ i = 1 p − 1 m i ( m o d p ) a p − 1 ∏ i = 1 p − 1 m i ≡ ∏ i = 1 p − 1 m i ( m o d p ) a p − 1 ≡ 1 ( m o d p ) 证 毕 考虑P=\{m_1,m_2,m_3,\cdots ,m_{p-1}\},m_i<p,显然有 m_i\not\equiv m_j\pmod p\\\because \gcd(a,p)=1\\\therefore 对于Q=\{a\cdot m_1,a\cdot m_2,a\cdot m_3,\cdots,a\cdot m_{p-1}\},也有 a\cdot m_i\not\equiv a\cdot m_j\pmod p\\~\\利用同余式的性质,我们对这两个两两元素之间不同余的集合联利,得\\\prod\limits_{i=1}^{p-1}a\cdot m_i\equiv \prod\limits_{i=1}^{p-1} m_i\pmod p\\a^{p-1}\prod\limits_{i=1}^{p-1} m_i\equiv \prod\limits_{i=1}^{p-1}m_i\pmod p\\a^{p-1}\equiv 1\pmod p\\证毕 P={m1,m2,m3,,mp1}mi<pmimj(modp)gcd(a,p)=1Q={am1,am2,am3,,amp1},amiamj(modp) i=1p1amii=1p1mi(modp)ap1i=1p1mii=1p1mi(modp)ap11(modp)

若对证明中的同余性质仍有不理解,可以看这里

利用费马小定理这个有力的工具,在判断 x x x 是否为质数时,我们或许会有这么一种思路:对于要判定的 x x x ,我们随机选择一个与 x x x 互质的底数 a a a ,若 a x − 1 ≡ 1 ( m o d x ) a^{x-1}\equiv 1\pmod x ax11(modx),则 x x x 为质数。

此方法被称为费马素性检验

稍微尝试,好像真的可行诶!但是别着急,这个想法是错误的,因为存在这么一类伪质数 (卡迈克尔数) x x x,也有 a x − 1 ≡ 1 ( m o d x ) a^{x-1}\equiv 1\pmod x ax11(modx),但 x x x 是合数!

因此,单独使用费马素性检验,在小部分情况下会对合数进行误判,所以我们还需要一个关于质数的定理进行二次判断。


二次探测定理

考 虑 p 为 质 数 , a 与 p 互 质 , 若 a 2 ≡ 1 ( m o d p ) , 则 有 p ∣ ( a 2 − 1 ) p ∣ ( a + 1 ) ( a − 1 ) ∴ p ∣ ( a + 1 ) 或 p ∣ ( a − 1 ) ∴ a ≡ ± 1   ∴ 若 a < p , a = p − 1 或 a = 1 考虑 p 为质数,a 与 p 互质,若 a^2\equiv 1\pmod p,则有\\ p\mid(a^2-1)\\ p\mid (a+1)(a-1)\\ \therefore p\mid (a+1) 或 p\mid (a-1)\\ \therefore a\equiv \pm1\\ ~\\ \therefore 若 a<p,a=p-1或a=1 papa21(modp)p(a21)p(a+1)(a1)p(a+1)p(a1)a±1 a<pa=p1a=1

因此,对于每个要判断的 x x x ,我们都随机选取一个底数 a < x a<x a<x,若 a 2 ≡ 1 ( m o d x ) a^2\equiv 1\pmod x a21(modx),则判断 a a a 是否为 1 1 1 x − 1 x-1 x1,是则 x x x 大概率是个质数,否则 x x x 一定不是个质数。

然而,二次探测定理也仍然会出现 “漏洞”,依旧存在一类合数 x x x 使得任意 a 2 ≡ 1 ( m o d x ) a^2\equiv 1\pmod x a21(modx) a ≠ 1 a\ne 1 a=1 a ≠ x − 1 a\ne x-1 a=x1

那么,费马素性检验和二次探测定理都不可行,是否说明我们要找到第三种 确定性 的定理来判断质数呢?也不需要。

我们可以考虑将费马素性检验与二次探测定理一起使用,对这个数是否为质数进行双重判断

那么,只有同时满足费马素性检验和二次探测定理的 x x x 是个质数。这是否一定正确呢?也是无法保证的,存在那么极少的合数,同时满足这两个定理。

但是显然,这种同时满足两个定理的合数,要比满足单一定理的合数要少的多。通俗的说,若一个数 x x x 满足同时满足两个定理,那么它是质数的概率可以达到 99 % 99\% 99%。而如果我们对同一个 x x x 都使用多个不同的底数 a a a 进行定理验证,那么这个误判的概率将进一步缩小,可以直接忽略。

因此,同时使用费马素性检验和二次探测定理 进行判素在 O I OI OI 数据范围内是个正确性保证的确定性算法,同时它也是 M i l l e r   R a b i n \mathbf{Miller\ Rabin} Miller Rabin 素性检验的原理所在。


Miller Rabin 算法

M i l l e r   R a b i n \mathbf{Miller\ Rabin} Miller Rabin 算法,即在程序上实现 M i l l e r   R a b i n \mathbf{Miller\ Rabin} Miller Rabin 素性检验,本质上也是在实现费马素性检验的判断中同时进行二次探测检验。

考虑判断 x x x 是否为质数,先将 x − 1 x-1 x1 分解为 2 k ⋅ t , k , t ∈ N 2^k\cdot t,k,t\in \N 2ktk,tN
选择一个 a a a 作为费马和二次探测的底数,然后使 a t a^t at 不断平方,在这个过程中运用二次探测定理检验,即判断是否当 ( a t ) 2 ≡ 1 ( m o d x ) (a^t)^2\equiv 1\pmod x (at)21(modx) a t ≡ ± 1 ( m o d x ) a^t\equiv \pm 1\pmod x at±1(modx),否则 x x x 不是质数。
很显然平方的过程执行 k k k 次后, a a a 的指数将变为 x − 1 x-1 x1,此时再运用费马素性检验判断是否 a x − 1 ≡ 1 ( m o d x ) a^{x-1}\equiv 1\pmod x ax11(modx),否则 x x x 不是质数

x x x 在上述过程中都没被 p a s s pass pass 掉,则 x x x 一定 大概率是个质数。

如果担心算法被卡,我们可以进一步降低误判的概率,使用多组底数 a a a 进行如上操作验证,只有当所用的所有的底数 a a a 都可以使得 x x x 满足两条定理时, x x x 才是质数。

底数 a a a 到底怎么取, w a n g r x \color{Red}wangrx\color{balck} wangrx 大佬给出了答案:

  • x ≤ 2 32 x\le 2^{32} x232 时,选取 2 , 7 , 612 , 7 , 61 2,7,612,7,61 2,7,612,7,61 三个底数即可
  • x ≤ 2 63 x\le 2^{63} x263 时,选取 2 , 325 , 9375 , 28178 , 450775 , 9780504 , 17952650222 , 325 , 9375 , 28178 , 450775 , 9780504 , 1795265022 2,325,9375,28178,450775,9780504,17952650222,325,9375,28178,450775,9780504,1795265022 2,325,9375,28178,450775,9780504,17952650222,325,9375,28178,450775,9780504,1795265022七个底数即可。

至此, M i l l e r R a b i n \mathbf{Miller Rabin} MillerRabin 素性检验本是一个带有不确定性的检验方法,但在 O I OI OI 数据范围内,我们可以通过增加底数的方式使其成为了一个确定性的算法,因此可以运用于实践当中。

CODE

#include <bits/stdc++.h>
#define int __int128
using namespace std;
long long t,x;
long long prime[9]={0,2,3,5,7,11,13,17,37}; //底数取值
int ksm(int a,int b,int mod)
{
	int sum=1;
	while(b)
	{
		if(b&1) sum=sum*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return sum%mod;
}
bool Miller_Rabin(int p,int a)
{
	int k=0,t=p-1,cnt;
	while(!(t&1)) t>>=1,k++;  //找到上述算法流程中的 t 和 k
	a=ksm(a,t,p);
	for(int i=1;i<=k;i++)
	{
		if(a*a%p==1)
		  if(a!=1&&a!=p-1) return false;  //二次探测定理
		 a=a*a%p;
	}
	if(a!=1) return false;  //费马素性检验判断
	return true;
}
bool isprime(int x)
{
	for(int i=1;i<9;i++)  //多次 Miller Rabin 验证
	{
		if(x==prime[i]) return true;
		if(x%prime[i]==0) return false;  //特判掉一些简单情况
		if(!Miller_Rabin(x,prime[i])) return false;
	}
	return true;
}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t)
	{
		t--;
		cin>>x;
		if(isprime(x)) cout<<"YES"<<'\n';
		else cout<<"NO"<<'\n';
	}
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值