Miller Rabin
Miller Rabin
在OI中的应用:判断一个数是否为素数
定理
Miller Rabin算法的依据需要费马小定理\(a^{p-1}\equiv 1(\bmod p)\)
它可以用欧拉定理和威尔逊定理证明,证明略qwq。
在费马小定理被证明后很长一段时间,人们都觉得这是显然的,但是在2016年,!!!人们给出了反例,攻破了这百年难题!!!也就是卡米切尔数的发现,推翻了这个结论
这是否意味着再利用费马小定理的思想去判断素数的思想就是错误的呢???
因为卡米切尔数的发现,所以这肯定是错误的。
但是我们可以人为降低出错概率,所以使用费马小定理判断也是很棒的!
于是Miller和Rabin两个外国大佬通过研究费马小定理,发明了Miller_Rabin算法进行素数测试。
首先介绍一下二次探测定理
若p维素数,那么 \(a^2\equiv 1(\bmod p)\),那么 \(a\equiv ± (\bmod p)\)
证明:
所以 \((a + 1)\equiv 0(\bmod p)\) 或者 \((a-1)\equiv 0(\bmod p)\)
即\(a\equiv ± 1(\bmod p)\)
那么二次探测定理和素数测试有什么关系呢?
现在来说一下Miller_Rabin算法流程
假设我们要判断的数是p
我们把p-1分解为\(2^k\times t\)的形式
当p是素数,有\(a^{2^k\times t} \equiv 1(\bmod p)\)
然后随机一个a,计算出\(a^t(\bmod p)\)
让其不断自乘,同时结合二次探测定理进行判断
如果我们自乘后的数\((\bmod p) = 1\),但是之前的数 \((\bmod p)\ne ± 1\)
那这个数就是合数,因为违背了二次探测定理
这样乘k此,最后得到的数就是\(a^{p-1}\)
如果最后计算出来的数不为1,这个数也是合数(费马小定理)
正确性
学长告诉我们,若p通过一次测试,则p不是素数的概率为 \(25\%\)
那经过t论测试,p不是素数的概率为 \(\frac{1}{4^t}\)
可以用几个质数进行判断,例如\(2,3,5,7,11,13,17,19\)
在信息学范围内出错率为 \(0\%\)(你要是高精就没意思了昂qwq)
Miller_Rabin
//出错率为0.006103515625%,很低的,放心用qwq
int text[] = {2, 3, 5, 7, 11, 13, 17};
int qpow(int num1, int num2) {
int ans = 1, base = num1;
while(num2) {
if(num2 & 1) ans *= base;
base *= base;
num2 >>= 1;
}
return ans;
}
bool check(int p) {
if(p == 1) return 0;
int t = p - 1, k = 0;
while(!(t & 1)) ++ k, t >>= 1;
for(int i = 0; i < 8; ++ i) {
if(p == test[i]) return 1;
ll a = qpow(text[i], t, p), nxt = a;
for(int j = 1; j <= k; ++ j) {
nxt = (a * a) % p;
if(nxt == 1 && a != 1 && a != p - 1) return 0;
a = nxt;
}
if(a != 1) return 0;
}
return 1;
}