定义:##

Miller Rabin算法是一个随机化素数测试算法,作用是判断一个数是否是素数,且只要你脸不黑以及常数不要巨大一般来讲都比\(O(\sqrt n)\)的朴素做法更快。

定理:##

Miller Rabin主要基于费马小定理:

\[a ^ {p-1} \equiv 1 (mod p)$$其中$p$是质数。
于是就有~~闲得没事干的~~一群科学家们想,这个问题的逆命题是否成立呢?

> 逆命题:若对于任意$a$,$a ^ {p-1} \equiv 1 (mod p)$都成立,那么$p$是质数。

在很长一段时间里,所有人几乎都以为它是成立的。~~然鹅你们手玩一个$a=8, p = 9$试试~~
是的,这个东西被搞出了反例。不过幸运的是,用这个办法测试通过的数,还是有很大概率是质数的。
这好办,我们多搞几次不就可以当做它就是质数了吗!~~脸黑另说~~

##算法流程:##
首先我们还得了解一个叫二次探测定理的东西:

> $$若p是质数,且x^2 \equiv 1 (mod p), 则有x \equiv ±1 (mod p)\]

证明很简单,第一个式子右边丢过去平方差即可。由于p是质数,所以它肯定不是\((x-1)和(x+1)\)凑起来的,故两个里面总有一个是\(p\)的倍数。

而且很容易脑补的是,这个东西的逆命题是成立的。(划重点)

所以根据这两个定理,我们设计一波算法:

假设我们要判断的数是\(p\),那么\(2\)特判一波,剩下的质数肯定是奇数。

所以\(p-1\)一定是一个偶数。然后就好办啦!

我们把\(p-1\)分解成\(2^k * t\),当\(p\)是素数时,根据费马小定理有$$a ^ {2^k * t} \equiv 1 (mod p)$$

那么我们随机出一个\(a\),然后求出\(a^t\),再不断乘上\(a\),每次进行二次探测,边乘边模,若乘之前不符合二次探测,而乘之后符合,那么p是合数,不符合题意。自乘\(k\)次,最后得到\(a^{p-1}\),如果模\(p\)不等于1,则也是合数。(不符合费马小定理)

老祖宗告诉我们(这个我也不会证),每一次通过测试的数不是质数的概率为\(\frac{1}{4}\),则测试\(k\)次,错误的概率为\(\frac{1}{4^k}\),\(k>6\)的时候基本就血赚了。

代码:##

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int c[23] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43};
int n, m;
inline ll read() {
ll cnt = 0, f = 1; char c;
c = getchar();
while (!isdigit(c)) {if (c == '-') f = -f; c = getchar();}
while (isdigit(c)) {cnt = (cnt << 3) + (cnt << 1) + c - '0'; c = getchar();}
return cnt * f;
}
inline ll ksm(ll a, ll b, ll c) {
ll ans = 1;
while (b) {
if (b & 1) ans = ans * a % c;
a = a * a % c, b >>= 1;
}
return ans % c;
}
bool miller_rabin(int p) {
if (p == 1) return false;
if (p == 2) return true;
if (p % 2 == 0) return false;
bool f = 1;
for (register int i = 0; i <= 13; ++i) {
if (c[i] == p) return true;
ll x = p - 1, y = 0;
while (x % 2 == 0) x /= 2, ++ y; // 将p-1分解成2^y*x
ll cur = ksm(c[i], x, p); //计算出a^x % p
if (cur == 1) continue; //小优化,如果此时结果为1,那么无论如何自乘也为1
for (register int j = 1; j <= y; ++j) {
ll nxt = cur * cur % p; //不断自乘
if (nxt == 1 && cur != p - 1 && cur != 1) {
f = 0;
break;
}
cur = nxt;
}
if (cur != 1) f = 0;
if (!f) break;
}
return f;
}
int main() {
n = read(); m = read();
while (m--) {printf(miller_rabin(read()) ? "Yes\n" : "No\n");}
return 0;
}

Miller Rabin算法学习笔记的更多相关文章

  1. C / C++算法学习笔记(8)-SHELL排序

    原始地址:C / C++算法学习笔记(8)-SHELL排序 基本思想 先取一个小于n的整数d1作为第一个增量(gap),把文件的全部记录分成d1个组.所有距离为dl的倍数的记录放在同一个组中.先在各组 ...

  2. Miller Rabin算法详解

    何为Miller Rabin算法 首先看一下度娘的解释(如果你懒得读直接跳过就可以反正也没啥乱用:joy:) Miller-Rabin算法是目前主流的基于概率的素数测试算法,在构建密码安全体系中占有重 ...

  3. Manacher算法学习笔记 | LeetCode#5

    Manacher算法学习笔记 DECLARATION 引用来源:https://www.cnblogs.com/grandyang/p/4475985.html CONTENT 用途:寻找一个字符串的 ...

  4. Pollard rho算法+Miller Rabin算法 BZOJ 3668 Rabin-Miller算法

    BZOJ 3667: Rabin-Miller算法 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 1044  Solved: 322[Submit][ ...

  5. Miller Rabin 算法简介

    0.1 一些闲话 最近一次更新是在2019年11月12日.之前的文章有很多问题:当我把我的代码交到LOJ上,发现只有60多分.我调了一个晚上,尝试用{2, 3, 5, 7, 11, 13, 17, 1 ...

  6. Johnson算法学习笔记

    \(Johnson\)算法学习笔记. 在最短路的学习中,我们曾学习了三种最短路的算法,\(Bellman-Ford\)算法及其队列优化\(SPFA\)算法,\(Dijkstra\)算法.这些算法可以快 ...

  7. 某科学的PID算法学习笔记

    最近,在某社团的要求下,自学了PID算法.学完后,深切地感受到PID算法之强大.PID算法应用广泛,比如加热器.平衡车.无人机等等,是自动控制理论中比较容易理解但十分重要的算法. 下面是博主学习过程中 ...

  8. 【数论基础】素数判定和Miller Rabin算法

    判断正整数p是否是素数 方法一 朴素的判定   

  9. Johnson 全源最短路径算法学习笔记

    Johnson 全源最短路径算法学习笔记 如果你希望得到带互动的极简文字体验,请点这里 我们来学习johnson Johnson 算法是一种在边加权有向图中找到所有顶点对之间最短路径的方法.它允许一些 ...

随机推荐

  1. Kunbernetes从私有仓库nexus拉取镜像

    1.docker登陆认证 [root@master ~]# vim /etc/docker/daemon.json { "insecure-registries": [" ...

  2. 20175323《Java程序设计》第二周学习总结

    一.教材学习内容总结 标识符第一个字符不能是数字且区分大小写数据类型转换时只允许把精度低的给精度高的,否则必须强制转换输入数据语法 Scanner reader = new Scanner(Syste ...

  3. (转)获取android手机内部存储空间和外部存储空间的参数 && 如何决定一个apk的安装位置

    转:http://blog.csdn.net/zhandoushi1982/article/details/8560233 获取android文件系统的信息,需要Environment类和StatFs ...

  4. yolo+keras+tensorflow出错:No module named 'leaky_relu'+

    结论:keras2.1.5+tensorflow1.6.0即可. 首先出现的是:No module named 'leaky_relu',此时把keras改成2.1.5照样出错,改成keras2.1. ...

  5. JAVA 文件的上传下载

    一.上传文件 1.使用 transferTo 上传 @ResponseBody @RequestMapping(value = "/file/upload") public Res ...

  6. vue中的data用return返回

    为什么在大型项目中data需要使用return返回数据呢? 答:不使用return包裹的数据会在项目的全局可见,会造成变量污染:使用return包裹后数据中变量只在当前组件中生效,不会影响其他组件. ...

  7. Mysql之DQL------基础查询

    #笔记内容来自于B站尚硅谷教学视频(av49181542)use myemployees; 查询表中的单个字段 SELECT last_name FROM employees; 查询表中的多个字段 # ...

  8. phonegap 拍照上传照片

    js代码 可以完全从  phonegap 官网扣下来 使用的是2.3版本的phonegap<script type="text/javascript" src="c ...

  9. naptime

    naptime 有一个长度为n的序列\(a_i\),首尾相接组成了一个环,现在要在这个环上选出若干个区间,使区间长度之和恰好为b,然后忽略区间的顺时针开头元素,权值累加区间中所有的数字,问权值的最大值 ...

  10. [JZOJ4648] 【NOIP2016提高A组模拟7.17】锦标赛

    题目 描述 题目大意 有nnn个人,你要确定一个出场序列.每次新上台的人就会和擂主打一架,胜利的人继续当擂主.题目给出两两之间打架胜利(失败)的概率. 问111选手坚持到最后的最大概率. 思考历程 看 ...