Miller-Rabin 素数检验算法
算法简介
Miller-Rabin算法,这是一个很高效的判断质数的方法,可以在用\(O(logn)\) 的复杂度快速判断一个数是否是质数。它运用了费马小定理和二次探测定理这两个筛质数效率极高的方法。
费马小定理判质数
\(a^{p - 1}\ ≡\ 1\ mod\ p\)
这个定理在 \(p\) 为质数的时候是成立的,所以我们可以如果要判断 \(p\) 是否是质数,可以 \(rand\) 几个 \(a\) 值然后照着这个式子来算,如果算出来不是 \(1\) 那说明 \(p\) 一定不是质数。
但在我们的自然数中,如果照着这个式子算出来的答案为1,也是有可能不是质数的。更有一类合数,它用费马小定理不管 rand 什么数都判不掉。这类合数称为 Carmichael数(卡迈克尔数),其中一个例子就是561(哇,居然这么小)。
二次探测定理
因为Carmichael数的存在,使得我们难以高效判断质数,所以我们还需要加入第二种判断方法使这种伪算法更优秀!而二次探测无疑就是为我们量身定制的算法,因为它要建立在同余式右边为1的基础上(而我们的费马小定理不正好满足了要求吗?)
若 \(b^2≡1\ mod\ p\) 且 \(p\) 为质数 \(=>\) 则 \(p\) 一定可以被 \(b−1\) 和 \(b+1\) 其中一个整除
这是二次探测定理,原理很简单,我们将上面的同余式左右都减1,根据平方差公式可以得出 \((b−1)(b+1)≡\ 0\ mod\ p\) 这其实就代表着等式左边是模数的倍数,但若模数p是质数,则 \((b−1)\) 和 \((b+1)\) 必定存在一个是 \(p\) 的倍数,所以要么 \(b−1=p\ (b=1)\) 或者 \(b+1=p\ (b=p−1)\) 如果不满足则 \(p\) 一定不是质数!然后我们还可以发现若 \(b=1\) 我们又可以进行新一轮二次探测!
根据这个道理,我们可以进行二次探测:因为 \(a^{p−1}≡1\mod\ p\) 如果 \(p−1\) 为偶数的话就可以化成: \(a^{(\frac{p−1}2)^2}≡1\ mod\ p\) 这样就变成了二次探测的基本式。
typedef long long ll;
typedef unsigned long long ull;
typedef long double lb;
inline ll ksc(ull x, ull y, ll p) { // O(1)快速乘(防爆long long)
return (x * y - (ull)((lb)x / p * y) * p + p) % p;
}
inline ll ksm(ll x, ll y, ll p) { //快速幂
ll res = 1;
while (y) {
if (y & 1) res = ksc(res, x, p);
x = ksc(x, x, p);
y >>= 1;
}
return res;
}
inline 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; //一定要为1,才能继续二次探测
}
return 1;
}
inline bool prime(ll x) {
if (x < 2) return 0;
if (x == 2 || x == 3 || x == 5 || x == 7 || x == 43) return 1;
return mr(2, x) && mr(3, x) && mr(5, x) && mr(7, x) && mr(43, x);
}
这样子加上二次探测之后,明显就能高效很多,基本上卡不了,大概要每 \(10^{10}\) 个数才会出现一个判不掉的,这个概率可以说十分微小,可以忽略!
Miller-Rabin 素数检验算法的更多相关文章
- Miller Rabin素数检测与Pollard Rho算法
一些前置知识可以看一下我的联赛前数学知识 如何判断一个数是否为质数 方法一:试除法 扫描\(2\sim \sqrt{n}\)之间的所有整数,依次检查它们能否整除\(n\),若都不能整除,则\(n\)是 ...
- POJ1811_Prime Test【Miller Rabin素数测试】【Pollar Rho整数分解】
Prime Test Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 29193 Accepted: 7392 Case Time ...
- POJ2429_GCD & LCM Inverse【Miller Rabin素数測试】【Pollar Rho整数分解】
GCD & LCM Inverse Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9756Accepted: 1819 ...
- POJ1811_Prime Test【Miller Rabin素数測试】【Pollar Rho整数分解】
Prime Test Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 29193 Accepted: 7392 Case Time ...
- HDU1164_Eddy'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 ...
- Miller Rabin素数检测
#include<iostream> #include<cstdio> #include<queue> #include<cstring> #inclu ...
- 关于素数:求不超过n的素数,素数的判定(Miller Rabin 测试)
关于素数的基本介绍请参考百度百科here和维基百科here的介绍 首先介绍几条关于素数的基本定理: 定理1:如果n不是素数,则n至少有一个( 1, sqrt(n) ]范围内的的因子 定理2:如果n不是 ...
- GCDLCM 【米勒_拉宾素数检验 (判断大素数)】
GCDLCM 题目链接(点击) 题目描述 In FZU ACM team, BroterJ and Silchen are good friends, and they often play some ...
- 【数论基础】素数判定和Miller Rabin算法
判断正整数p是否是素数 方法一 朴素的判定
随机推荐
- dhtmlxGantt独立安装的系统要求
dhtmlxGantt库提供了使用导出作为在线服务从甘特图导出和导入数据的可能性. 您还可以通过在计算机上安装导出服务来本地导出甘特图.您需要确保系统满足系统要求才能使用导出模块: PNG / PDF ...
- 安卓app功能或自动化测试覆盖率统计(不用instrumentation启动app)
一文带你揭秘如何采取非instrumentation启动app,打造实时统计覆盖率,一键触发覆盖率测试报告. 在上篇文章,一文带你解决Android app手工测试或者自动化测试覆盖率统计(撸代码版) ...
- 092 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 02 static关键字 02 static关键字(中)
092 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 ...
- Java知识系统回顾整理01基础02面向对象02属性
一.根据实例给出"属性"的定义 一个英雄有姓名,血量,护甲等等状态 这些状态就叫做一个类的属性 二.属性的类型 属性的类型可以是基本类型,比如int整数,float 浮点数 也可以 ...
- VID和PID
今天很在一份datasheet上突然看到 VID 和 PID 很奇怪!!还不是很懂!!! 参考:https://blog.csdn.net/gaojinshan/article/details/787 ...
- Arduino各开发板
参考来源:https://www.arduino.cn/thread-42417-1-1.html 查了好久,发现除了奈何等等几位大神总结过arduino各板子之间的性能.差异,没有很新的分析文章,在 ...
- java进阶(26)--ForEach
JDK5.0后新特性 一.普通for循环
- BeetleX之webapi自定义响应内容
输出内容多样性在webapi服务中比较普遍的,有的情况使用json,xml,图片和二进制流下载等等:为了适应用不同情况的需要,组件支持自定义内容输出.接下来的主要描述组件在webapi如何定义各种内容 ...
- Jmeter请求之接口串联自动化测试(未完)
方案一:添加Cookie管理器,把用户的登录状态存在cookie管理器中,类似于浏览器 存储测试结果: 监听器->保存响应到文件,对结果进行存储 文件名前缀:保存到哪个地方前缀是什么D:\tes ...
- 【C语言教程】“双向循环链表”学习总结和C语言代码实现!
双向循环链表 定义 双向循环链表和它名字的表意一样,就是把双向链表的两头连接,使其成为了一个环状链表.只需要将表中最后一个节点的next指针指向头节点,头节点的prior指针指向尾节点,链表就能成环儿 ...