【代码超详解】LOJ #143 质数判定(Miller-Rabin算法 · 模板题)

一、题目描述

#143. 质数判定

内存限制:256 MiB
时间限制:5000 ms
标准输入输出
题目类型:传统
评测方式:文本比较
上传者: fjzzq2002

题目描述

判定输入的数是不是质数。

输入格式

若干行,一行一个数x 。

行数不超过1e5 。

输出格式

对于输入的每一行,如果 x是质数输出一行

Y

否则输出一行

N

样例

样例输入

1
2
6
9
666623333

样例输出

N
Y
N
N
Y

数据范围与提示

1 ≤ x ≤1e18
欢迎hack(如果你不是管理员,可以在题目讨论区发帖)。

二、算法分析说明与代码编写指导

【代码超详解】LOJ #143 质数判定(Miller-Rabin算法 · 模板题)_第1张图片
【代码超详解】LOJ #143 质数判定(Miller-Rabin算法 · 模板题)_第2张图片

三、AC 代码

尼玛,这题巨几把毒瘤,搞了我整整3天。

快速幂要用__int128作为中间变量类型的版本,不然各种WA。不过VS是没有支持这个类型的,就没法本地调试了,除非临时改掉这个类型,提交的时候改回去。LOJ和洛谷都可以支持__int128,HDU不行。

这题好多网上AC代码根本就不能全部数据都过,估计数据是反复被加强过了。

老子就想找个说得清楚点的Miller-Rabin算法的解释和对应代码,结果这么多代码全都过不了。至于上面的算法概述,这里抄一点那里借来改一下再补充一些注意事项,再缩减一下,就成了现在这样子。整理过程真是吐血啊。

#include
#include
#pragma warning(disable:4996)
using namespace std;
unsigned long long x, prime[] = { 2,3,5,7,11,13,17,19,23 }, * prime_end = prime + sizeof(prime) / sizeof(prime[0]);
template<typename _RTy, typename _Ty1, typename _Ty2, typename _Ty3> inline _RTy PowerMod(const _Ty1& radix, const _Ty2& exp, const _Ty3& mod) {
	__int128 ans = 1, R = radix % mod, X = exp, M = mod;
	while (X) {
		if (X & 1)ans = (ans * R) % M;
		X >>= 1, R = (R * R) % M;
	}return ans % M;
}
template<typename _Ty> inline bool MillerRabin(const _Ty& x) {
	for (auto B = prime; B != prime_end; ++B) {
		if (x == *B)return true;
		if (x < *B)return false;
		_Ty y = x - 1, x0 = y, r = PowerMod<_Ty>(*B, y, x);
		if (r != 1)return false;
		for (; (y & 1) == 0 && r == 1;) {
			y >>= 1, r = PowerMod<_Ty>(*B, y, x); if (r != 1 && r != x0)return false;
		}
	}
	return true;
}
int main() {
	for (;;) {
		if (scanf("%llu", &x) == EOF)return 0;
		switch (MillerRabin(x)) {
		case true:puts("Y"); continue;
		case false:puts("N");
		}
	}
}

你可能感兴趣的:(ACM-ICPC)