【技能点】Miller_Rabin算法(大质数判定)

  1. 一个数 p p p如果是质数,那么一定满足费马小定理, x p − 1 ≡ 1 ( m o d   p ) x^{p-1}\equiv1(mod\ p) xp11(mod p)
  2. 对于能满足 条 件 1 条件1 1的数 p p p,显然不一定都是质数。所以需要进行所谓的二次探测。
    即若 p p p是质数且 x 2 ≡ 1 ( m o d   p ) x^2\equiv1(mod\ p) x21(mod p),则 x ≡ 1 ( m o d   p ) x\equiv1(mod\ p) x1(mod p) x ≡ p − 1 ( m o d   p ) x\equiv p-1(mod\ p) xp1(mod p)

二次探测证明如下:
x 2 ≡ 1 ( m o d   p ) x 2 − 1 ≡ 0 ( m o d   p ) ( x − 1 ) ( x + 1 ) ≡ 0 ( m o d   p ) p ∣ ( x − 1 ) ( x + 1 ) \begin{aligned} x^2\equiv1(&mod\ p)\\ x^2-1\equiv&0(mod\ p)\\ (x-1)(x+1&) \equiv0(mod\ p)\\ p|(x-1&)(x+1) \end{aligned} x21(x21(x1)(x+1p(x1mod p)0(mod p))0(mod p))(x+1)
∵ \because 质数 p p p只有 1 1 1和他本身两个因数
∴ \therefore 所以必定有 p ∣ x − 1 p|x-1 px1 p ∣ x + 1 p|x+1 px+1
x − 1 ≡ 0 ( m o d   p ) x-1\equiv0(mod\ p) x10(mod p) x + 1 ≡ 0 ( m o d   p ) x+1\equiv0(mod\ p) x+10(mod p)
解得 x ≡ 1 ( m o d   p ) x\equiv1(mod\ p) x1(mod p) x ≡ p − 1 ( m o d   p ) x\equiv p-1(mod\ p) xp1(mod p)

所以算法流程如下:

  1. 先用费马小定理进行判断
  2. 如果 p − 1 p-1 p1是偶数,则有 x p − 1 ≡ 1 ( m o d   p ) ⇒ ( x p − 1 2 ) 2 ≡ 1 ( m o d   p ) x^{p-1}\equiv1(mod\ p)\Rightarrow (x^{\frac{p-1}{2}})^2\equiv1(mod\ p) xp11(mod p)(x2p1)21(mod p),所以可以不断循环用二次探测判定。

由于Miller_Rabin算法再判断的时候容易出现失误,所以我们最好选择多个 x x x进行测试判定。
我们在选择 x x x的时候,最好选择质数。显然当我们选择的 x x x质数越多,第一判断失误的数 T T T也会越大。
有人发现,选择 { 2 , 3 , 7 , 61 , 24251 } \{2,3,7,61,24251\} {2,3,7,61,24251} 5 5 5个数作为底数的时候,在 1 0 16 10^{16} 1016的范围内,只有判断 46856248255981 46856248255981 46856248255981时会出现失误,这个数会被判定为素数,而他是个合数 46856248255981 = 4840261 ∗ 9680521 46856248255981=4840261*9680521 46856248255981=48402619680521

也有一篇文章《64位以内Rabin-Miller 强伪素数测试和Pollard rho 因数分解算法的实现》提到,
选取前 k k k个素数为基进行测试判定,并用 ψ k \psi_k ψk表示以前 k k k个素数为基进行素数判定第一个出现失误的合数,Riesel在1994年给出下表:
ψ 1 = 2 , 047 ψ 2 = 1 , 373 , 653 ψ 3 = 25 , 326 , 001 ψ 4 = 3 , 215 , 031 , 751 ψ 5 = 2 , 152 , 302 , 898 , 747 ψ 6 = 3 , 474 , 749 , 660 , 383 ψ 7 = 341 , 550 , 071 , 728 , 321 ψ 8 = 341 , 550 , 071 , 728 , 321 ψ 9 ≤ 41 , 234 , 316 , 135 , 705 , 689 , 041 ψ 10 ≤ 1 , 553 , 360 , 566 , 073 , 143 , 205 , 541 , 002 , 401 ψ 11 ≤ 56 , 897 , 193 , 526 , 942 , 024 , 370 , 326 , 972 , 321 \begin{aligned} \psi_1&=2,047\\ \psi_2&=1,373,653\\ \psi_3&=25,326,001\\ \psi_4&=3,215,031,751\\ \psi_5&=2,152,302,898,747\\ \psi_6&=3,474,749,660,383\\ \psi_7&=341,550,071,728,321\\ \psi_8&=341,550,071,728,321\\ \psi_9&≤41,234,316,135,705,689,041\\ \psi_{10}&≤1,553,360,566,073,143,205,541,002 ,401\\ \psi_{11}&≤56,897,193,526,942,024,370,326,972,321\\ \end{aligned} ψ1ψ2ψ3ψ4ψ5ψ6ψ7ψ8ψ9ψ10ψ11=2,047=1,373,653=25,326,001=3,215,031,751=2,152,302,898,747=3,474,749,660,383=341,550,071,728,321=341,550,071,728,32141,234,316,135,705,689,0411,553,360,566,073,143,205,541,002,40156,897,193,526,942,024,370,326,972,321

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
#define ull unsigned long long
#define ld long double
#define inl inline
#define re register
#define MAXN 10100
using namespace std;
inl ll ksc(ull x,ull y, ll p){return (x*y-(ull)((ld)x/p*y)*p+p)%p;}
inl ll ksm(ll x,ll y,ll p)
{
	ll res=1;
	for(;y;y>>=1,x=ksc(x,x,p))if(y&1)res=ksc(res,x,p);
	return res;
}
inl bool mr(ll x,ll p)
{
	if(ksm(x,p-1,p)!=1)return 0;
	ll y=p-1,z;
	while(!(y&1))
	{
		y>>=1;z=ksm(x,y,p);
		if(z!=1&&z!=p-1)return 0;
		if(z==p-1)return 1;
	}
	return 1;
}
int te_pri[20]={0,2,3,5,7,43,61,24251},te_num=7;
inl bool isprime(ll x)
{
	if(x<2)return 0;
	for(int i=1;i<=te_num;i++)
		if(x==te_pri[i])return 1;
	for(int i=1;i<=te_num;i++)
		if(!(x%te_pri[i])||!mr(te_pri[i],x))return 0;
	return 1;
}
int main()
{
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值