「学习笔记」素性测试

给定一个正整数 n,判断它是否是质数。

Fermat 素性测试#

根据费马小定理,如果 n 是质数,则会满足 an11(modn)
基本思想是不断地选取在 [2,n1] 中的基 a,并检验是否每次都有 an11(modn)
如果 an1modn=1n 不是素数,则 n 被称为以 a 为底的伪素数。我们在实践中观察到,如果 an1modn=1,那么 n 通常是素数。但这里也有个反例:如果 n=341a=2,即使 341=1131 是合数,有 23401(mod341)。事实上,341 是最小的伪素数基数。
因此很遗憾,费马小定理的逆定理并不成立,换言之,满足了 an11(modn)n 也不一定是素数。

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 二人根据费马小定理的逆定理(费马测试)优化得到的。

二次探测原理#

如果 p 是奇素数,则 x21(modp) 的解为 x1(modp) 或者 xp1(modp)
证明:

x21(modp)x210(modp)(x+1)(x1)0(modp)

又因为 p 是质数,所以只能有 (x+1)0(modp) 或者 (x1)0(modp)
所以 xp1(modp) 或者 x1(modp)


不妨将费马小定理和二次探测定理结合起来使用:
an11(modn) 中的指数 n1 分解为 n1=u×2t,在每轮测试中对随机出来的 a 先求出 v=aumodn,之后对这个值执行最多 t 次平方操作,若发现非平凡平方根时即可判断出其不是素数,否则再使用 Fermat 素性测试判断。

同余方程 x21(modn)x±1(modn) 的任何根称为“以 n 为模的 1 的非平凡平方根”。 若 n 存在以 n 为模的 1 的非平凡平方根,则 n 是合数。
x1(modn) 可以看作是 x1+p(modn),即 xp1(modn)

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 国际」许可协议进行许可。

转载时还请标明出处哟!

posted @   yi_fan0305  阅读(196)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示