Miller-Rabin素数检测算法

其基于以下两个定理。

  1. Fermat小定理

    若n是素数,则∀a(a̸≡0(modn))\forall a(a \not\equiv 0 \pmod{n})∀a(a̸​≡0(modn)),有an−1≡1(modn)a^{n-1} \equiv 1 \pmod{n}an−1≡1(modn).

  2. 二次探测定理

    若n是素数,则x2≡1(modn)x^2 \equiv 1 \pmod{n}x2≡1(modn)只有平凡根x=±1x=\pm1x=±1,即x=1,x=n−1x=1,x=n-1x=1,x=n−1.

费马小定理鼎鼎有名,而二次探测定理由ZpZ_pZp​是域,域中无零因子容易得到。

注意这两个定理都是叙述了素数的必要条件,而Miller-Rabin对于要检验的n,是选取若干个a,检验是否满足这两个必要条件。显然,如果某个必要条件不满足,那么断言不是素数是正确的。但是,选了好几个a,都满足这两个必要条件,n是质数还是合数是无法确定的,但是Miller-Rabin算法选择忽略这一点,直接断言n是素数。

换句话说,Miller-Rabin算法断言一个数不是素数一定是正确的,断言一个数是素数,则可能是错误的。但是,实际上,会被误判为素数的合数,是很少的。而且每选取一个符合条件的a,通过检验出错的概率不超过12\frac{1}{2}21​.因此实际应用中使用Miller-Rabin算法是可行的。

实际上,选取一个a,仅仅基于费马小定理给出的必要条件做断言的检测算法,被错误断言为素数的合数称作基于a的伪素数

而通过选取各个符合条件的a,仅仅基于费马小定理,进行断言的检测算法,被错误断言为素数的伪素数就是卡迈克尔数

具体算法

假设nnn是奇数,令n=m×2q(q≥1)n=m \times 2^q (q \geq 1)n=m×2q(q≥1),其中mmm是奇数.

对于序列am mod n,a2m mod n,a4m mod n,…,a2q×m mod na^m \bmod n, a^{2m} \bmod n, a^{4m} \bmod n,\ldots,a^{2^q \times m} \bmod nammodn,a2mmodn,a4mmodn,…,a2q×mmodn.

最后一项就是费马小定理中的an−1a^{n-1}an−1, 并且每一项都是前一项的平方。

我们一项一项往后计算。

  • 若当前项为1,后面每一项显然都是1。而根据二次探测定理,n是素数必须前面一项是1或n-1.如果不符合,断言不是素数;符合,断言是素数。

  • 若当前项不是1,暂时不断言,接着往后算。除非当前是最后一项了,那么断言不是素数。

当然,如果第一项是1,由于不存在二次探测的方程,所以不检验前面一项(或者认为前面一项符合条件)。

Code

使用了快速幂模和快速幂加模板mod_sys。下面代码只是miller-rabin核心代码。

 // 如果只是int范围内,可以将pow_v2改为pow,mlt改为普通乘法
bool miller_rabin(ll a, ll n, ll q, ll m, mod_sys& mod) {
a = mod.pow_v2(a, m);
bool is_ordinary = true;
for (int i = 0; i < q; ++i) {
if (a == 1) {
return is_ordinary;
} else {
is_ordinary = (a == n-1);
a = mod.mlt(a,a);
}
}
return (a==1)&&(is_ordinary); // 最后一项
} // 使用miller_rabin检测是否是素数
const int kCheckCnt = 8;
// 为了随机数
random_device rd;
mt19937_64 gen(rd());
bool miller_rabin(ll n) {
if (n == 2) return true;
if ((n <= 2) || (n&1^1)) return false;
// 2^q×m表示原本输入的n-1
ll m = n, q = 0;
do { m >>= 1; ++q; } while(m&1^1);
// 随机数生成,[1,n-1] 均匀分布
uniform_int_distribution<> dis(1, n-1);
mod_sys mod;
mod.set_mod(n);
for (int i = 0; i < kCheckCnt; ++i)
if (!miller_rabin(dis(gen), n, q, m, mod))
return false;
return true;
}

模板题推荐hdu2138

Miller-Rabin素数检测算法 acm模板的更多相关文章

  1. Miller Rabin素数检测与Pollard Rho算法

    一些前置知识可以看一下我的联赛前数学知识 如何判断一个数是否为质数 方法一:试除法 扫描\(2\sim \sqrt{n}\)之间的所有整数,依次检查它们能否整除\(n\),若都不能整除,则\(n\)是 ...

  2. Miller Rabin素数检测

    #include<iostream> #include<cstdio> #include<queue> #include<cstring> #inclu ...

  3. POJ1811_Prime Test【Miller Rabin素数测试】【Pollar Rho整数分解】

    Prime Test Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 29193 Accepted: 7392 Case Time ...

  4. POJ2429_GCD &amp; LCM Inverse【Miller Rabin素数測试】【Pollar Rho整数分解】

    GCD & LCM Inverse Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9756Accepted: 1819 ...

  5. POJ1811_Prime Test【Miller Rabin素数測试】【Pollar Rho整数分解】

    Prime Test Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 29193 Accepted: 7392 Case Time ...

  6. HDU1164_Eddy&#39;s research I【Miller Rabin素数测试】【Pollar Rho整数分解】

    Eddy's research I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  7. Miller-Rabin素数检测算法

    遇到了一个题: Description: Goldbach's conjecture is one of the oldest and best-known unsolved problems in ...

  8. 关于素数:求不超过n的素数,素数的判定(Miller Rabin 测试)

    关于素数的基本介绍请参考百度百科here和维基百科here的介绍 首先介绍几条关于素数的基本定理: 定理1:如果n不是素数,则n至少有一个( 1, sqrt(n) ]范围内的的因子 定理2:如果n不是 ...

  9. 【数论基础】素数判定和Miller Rabin算法

    判断正整数p是否是素数 方法一 朴素的判定   

随机推荐

  1. 【WPF学习】第四十一章 变换

    通过使用变换(transform),许多绘图任务将更趋简单:变换是通过不加通告地切换形状或元素使用的坐标系统来改变形状或元素绘制方式的对象.在WPF中,变换由继承自System.Windows.Med ...

  2. [pathlib]内置pathlib库的常用属性和方法

    pathlib中的Path类可以创建path路径对象, 属于比os.path更高抽象级别的对象. 官网 from pathlib import Path path = Path(__file__) p ...

  3. 谈python3的封装

    这章给大家介绍,如何封装一个简单的python库 首先创建一个以下型式的文件结构 rootFile/ setup.py example_package/ __init__.py example_mod ...

  4. win10系统下安装JDK1.8及配置环境变量的方法

    本次演示基于windows10操作系统,如果你是linux,请参考:https://www.yn2333.com/archives/linux上安装JDK8 1:下载安装包 地址:https://ww ...

  5. Jmeter之存储测试结果

    前言 Jmeter做接口测试时,发送请求后,我们可以通过察看结果树看到结果,但是如果想要把测试结果保存起来,那该怎么做呢? 一:添加一个登录的http请求,填入正确的ip,接口地址,以及参数 二:右键 ...

  6. golang 运算符

    /* 算术运算符 : + - * / % ++ -- 关系运算符 : == != > < >= <= 逻辑运算符 : && || ! 赋值运算符 : = += ...

  7. LwIP的udp学习笔记

    * Bind an UDP PCB. * * @param pcb UDP PCB to be bound with a local address ipaddr and port. * @param ...

  8. ELK-图示nginx中ip的地理位置

    一.环境准备: ELK stack 环境一套 geolite数据库文件 二.下载geolite数据库(logstash机器上解压,logstash需调用): geolite官网:https://dev ...

  9. [MSSQL]xp_cmdshell 查看磁盘空间

    EXEC xp_cmdshell 'wmic logicaldisk get freespace,caption | findstr C'; <class 'pyodbc.Row'> (' ...

  10. 使用Webpack的代码拆分在Vue中进行懒加载

    参考学习:https://alexjover.com/blog/lazy-load-in-vue-using-webpack-s-code-splitting/ 学习文案:https://webpac ...