「学习笔记」素性测试
给定一个正整数 ,判断它是否是质数。
Fermat 素性测试#
根据费马小定理,如果 是质数,则会满足 。
基本思想是不断地选取在 中的基 ,并检验是否每次都有 。
如果 但 不是素数,则 被称为以 为底的伪素数。我们在实践中观察到,如果 ,那么 通常是素数。但这里也有个反例:如果 且 ,即使 是合数,有 。事实上, 是最小的伪素数基数。
因此很遗憾,费马小定理的逆定理并不成立,换言之,满足了 , 也不一定是素数。
bool millerRabin(int n) {
if (n < 3) return n == 2;
// test_time 为测试次数,建议设为不小于 8 的整数以保证正确率,但也不宜过大,否则会影响效率
for (int i = 1; i <= test_time; ++i) {
int a = rand() % (n - 2) + 2;
if (qpow(a, n - 1, n) != 1) return 0;
}
return 1;
}
Miller-Rabin 素性测试#
Miller-Rabin 素性测试(Miller–Rabin primality test)是进阶的素数判定方法。它是由 Miller 和 Rabin 二人根据费马小定理的逆定理(费马测试)优化得到的。
二次探测原理#
如果 是奇素数,则 的解为 或者 。
证明:
又因为 是质数,所以只能有 或者 。
所以 或者 。
不妨将费马小定理和二次探测定理结合起来使用:
将 中的指数 分解为 ,在每轮测试中对随机出来的 先求出 ,之后对这个值执行最多 次平方操作,若发现非平凡平方根时即可判断出其不是素数,否则再使用 Fermat 素性测试判断。
同余方程 除 的任何根称为“以 为模的 的非平凡平方根”。 若 存在以 为模的 的非平凡平方根,则 是合数。
可以看作是 ,即
bool millerRabin(int n) {
if (n < 3 || n % 2 == 0) return n == 2;
int u = n - 1, t = 0;
while (u % 2 == 0) u /= 2, ++t;
// test_time 为测试次数,建议设为不小于 8 的整数以保证正确率,但也不宜过大,否则会影响效率
for (int i = 0; i < test_time; ++i) {
int a = rand() % (n - 2) + 2, v = qpow(a, u, n);
if (v == 1) continue;
int s;
for (s = 0; s < t; ++s) {
if (v == n - 1) break; // 得到平凡平方根 n-1,通过此轮测试
v = 1ll * v * v % n;
}
// 如果找到了非平凡平方根,则会由于无法提前 break; 而运行到 s == t
// 如果 Fermat 素性测试无法通过,则一直运行到 s == t 前 v 都不会等于 -1
if (s == t) return 0;
}
return 1;
}
作者:yifan0305
出处:https://www.cnblogs.com/yifan0305/p/17038417.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
转载时还请标明出处哟!
朝气蓬勃 后生可畏
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!