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. HDU2066dijkstra模板题

    问题描述: 题目描述:Problem Description 虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中    会遇见很多人(白马王 ...

  2. HDU_3183_RMQ

    http://acm.hdu.edu.cn/submit.php?pid=3183 初探rmq,这道题看了题解还是写了好久.原因是rmq处理字符串时没有自己写min函数,导致把返回的字符当成下标处理了 ...

  3. ARTS Week 12

    Jan 13, 2020 ~ Jan 19, 2020 Algorithm Problem 112. Path Sum (路径总和) 题目链接 题目描述:给定一棵二叉树和一个值 sum ,检查二叉树是 ...

  4. bootstrap 按钮组件

    按钮组件主要的类名: .btn-toolbar     把几个  .btn-group 组合在一起,更复杂的组件 .btn-group .btn-group-vertical   垂直堆叠显示    ...

  5. Go语言实现:【剑指offer】二维数组中的查找

    该题目来源于牛客网<剑指offer>专题. 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一 ...

  6. Nginx总结(八)Nginx服务器的日志管理及配置

    前面讲了如何配置Nginx虚拟主机,大家可以去这里看看nginx系列文章:https://www.cnblogs.com/zhangweizhong/category/1529997.html 今天要 ...

  7. 详解SkipList跳跃链表【含代码】

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天继续介绍分布式系统当中常用的数据结构,今天要介绍的数据结构非常了不起,和之前介绍的布隆过滤器一样,是一个功能强大原理简单的数据结构.并且 ...

  8. html input元素的所有type属性

    <input /> 属性 type="text" 输入框的类型为文本 type="password" 输入框的类型为密码 type="ra ...

  9. java 获取两个时间之前所有的日期

    正序(2017-01-01 ~2019-xxxxx) package com.founder.util; import java.text.SimpleDateFormat; import java. ...

  10. Hibernate入门之命名策略(naming strategy)详解

    前言 JPA和Hibernate都提供了默认映射策略,通过映射将每个实体类映射到具有相同名称的数据库表,它的每个属性都映射到具有相同属性的列, 但是,在实际项目开发中可能出现与默认命名约定不匹配,也就 ...