用来干嘛的

​   要判断一个数 \(n\) 是否为素数,最朴素直接的办法是以\(O(\sqrt n)\) 时间复杂度地从2到 \(\sqrt n\) 循环即可得到最准确的结果。但是如果在 \(n\) 比较大的情况下,时间花销就太大了。这时,我们可以选择牺牲一点点准确度,使用可爱的米勒-拉宾(Miller-Rabin)素性检验算法来判断质数。根据百度百科,使用快速幂运算,这个算法的时间复杂度是 \(O(k\log^3 n)\)的,\(k\)是我们设定对一个数的进行测试的次数。\(k\) 越大,判断错误的几率越低,保守估计大概是\(4^{-k}\),实际效果极佳,我们一般取到10就可以了。

谁搞出来的(摘自百度百科)

​  米勒-拉宾素性检验是一种素数判定法则,利用随机化算法判断一个数是合数还是可能是素数。卡内基梅隆大学的计算机系教授Gary Lee Miller首先提出了基于广义黎曼猜想的确定性算法,由于广义黎曼猜想并没有被证明,其后由以色列耶路撒冷希伯来大学的Michael O. Rabin教授作出修改,提出了不依赖于该假设的随机化算法。

要用到的数学定理

费马小定理:

​  如果\(p\)是一个质数,而且整数\(a\)与\(p\)互质(即最小公因数\(gcd(a,p) = 1\)),则有\(a^{p-1}≡1(mod~p)\)(模\(p\)同余符号)。但是这个命题的逆命题不一定能判断一个数是否为素数,只能说明不满足\(a^{p-1}≡1(mod~p)\)条件的 \(p\) 一定是合数。在本算法里,主要就是运用了它的逆命题来检验素数的。

证明:不会,感兴趣的同学可以自己搜索相关证明(很多种),用完全剩余系的证明方法比较容易理解

二次探测定理:

​  若 \(n\) 为大于2的素数,则对于任意整数 \(a∈[1,n-1]\),使方程\(a^2=1(mod~n)\)成立的解有仅有\(a=1\)或者\(a=n-1\)。在算法中同样通过判断是否可以满足这个解情况,增强素数判断的准确性。

证明:还是不会,其实挺好证明的。这位博主的分析比较详细,可以看看

算法流程

​  首先对于一个数 \(num\),先判断是不是偶数和小于等于2这两种可以直接筛掉的情况。如果不是,那么就正式进入判断流程了。\(num\) 必为奇数,则\(num-1\)一定是个偶数,而偶数可以分解为\(2^s \cdot t = num-1\)的形式。这里如果我们让两边作为一个整数\(a\)的指数,不就可以利用费马小定理\(a^{num-1}≡1(mod~num)\)来检验 \(num\) 是否为素数了吗?别急,在算出 \(a^{2^s \cdot t}\) 的过程中,我们可以顺便利用二次探测定理来检测,大大提高我们判断的准确度。我们的做法是先随机产生一个比 \(num\) 小的整数 \(a\) ,先计算出\(a^t\) ,在我下面的代码中把这个值记作 \(x\)。然后循环 \(s\) 次,每次都用一个变量 \(test\) 记录 \(x^2\) 对 \(num\) 取模的值,如果 \(test = 1\)则说明\(x^2=1(mod~num)\)成立,进而可以判断 \(x\) 是否为1或者\(num-1\) ,如果\(x\) 都不是则说明 \(num\) 肯定不是素数啦。反复运用 \(s\) 次二次探测定理,最后再判断一次\(a^{2^s \cdot t}≡1(mod~num)\)是否成立,如果过了最后费马小定理这关,恭喜这个 \(num\) 经过了第一层考验。我们对 \(num\) 进行 \(k\) 次这样的考验,每次取一个不同的 \(a\) ,如果始终没有返回 ,则说明 \(num\) 最终通过了 \(Miller\) 测试。

c++代码

​  码风极丑警告,注释过多。需要用到快速幂和快速(也叫龟速)乘(不会的同学可以百度一下哦)。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll ;//miller-rabin素数检验一般应用于大数的快速检测,用long long //快速乘,代替乘法,防止a乘b爆long long
ll qMul(ll a,ll b,ll mod){
ll ans = 0;//a乘b等价转化为b个a相加,和快速幂原理一致
while(b){
if(b&1) ans = (ans+a)%mod;
a = (a+a)%mod;
b>>=1;
}
return ans;
} //快速幂模板
ll qPow(ll base,ll power,ll mod){
ll ans = 1;
while(power){
if(power&1) ans = qMul(ans,base,mod);
base = qMul(base,base,mod);
power>>=1;
}
return ans%mod;
} //miller-rabin素数检验函数
bool Miller_Rabin(ll num){
if(num == 2) return true; //2为质数
if(!(num&1)||num<2) return false;//筛掉偶数和小于2的数
ll s = 0,t = num-1; //流程中的s和t,2的s次方*t = num-1
while(!(t&1)){ //当t为偶数的时候,可以继续分解
s++;
t>>=1;
}
for (int i = 1; i <= 10; i++) { //进行十次测试即可得到比较准确的判断
ll a = rand()%(num-1)+1; //流程中的随机整数a,在1到num-1之间
ll x = qPow(a,t,num); //x为二次探测的解
for(int j = 1;j <= s;j++){ //x平方s次可以得到a的num-1次方
ll test = qMul(x,x,num); //test为x平方后对num取模
if(test == 1 && x != 1 && x != num-1) return false; //如果平方取模结果为1,但是作为解的x不是1或者num-1,说明num不是质数,返回
x = test;
}
if(x != 1) return false; //费马小定理作最后检测,a的num-1次方对num取模不等于1,一定不是质数
}
return true; //腥风血雨后仍坚持到最后,基本就是真正的质数了
} int main(){
ll num;
while(cin>>num){
if(Miller_Rabin(num)) cout<<num<<" is a prime."<<endl;
else cout<<num<<" is not a prime."<<endl;
}
return 0;
}

题目

牛客NC14703素数回文

​  我就是看了这道题才想去学Miller-Rabin素数检测的(实际上用朴素的方法也能过),用Miller-Rabin可以比朴素的算法快十倍(如果哪一天被卡了别打我)。感兴趣的可以去做一下,搞出回文数后套Miller-Rabin算法判断即可,注意要开long long。

博客园第一篇博文,谢谢观看ヾ(≧▽≦*)o,如果觉得有帮助请给我点个小心心 (*>.<*)

Miller-Rabin素数测试算法的更多相关文章

  1. POJ1811_Prime Test【Miller Rabin素数测试】【Pollar Rho整数分解】

    Prime Test Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 29193 Accepted: 7392 Case Time ...

  2. HDU1164_Eddy&#39;s research I【Miller Rabin素数测试】【Pollar Rho整数分解】

    Eddy's research I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  3. Miller Rabin素数检测与Pollard Rho算法

    一些前置知识可以看一下我的联赛前数学知识 如何判断一个数是否为质数 方法一:试除法 扫描\(2\sim \sqrt{n}\)之间的所有整数,依次检查它们能否整除\(n\),若都不能整除,则\(n\)是 ...

  4. POJ2429_GCD &amp; LCM Inverse【Miller Rabin素数測试】【Pollar Rho整数分解】

    GCD & LCM Inverse Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9756Accepted: 1819 ...

  5. Miller-Rabin素数测试算法(POJ1811Prime Test)

    题目链接:http://poj.org/problem?id=1811 题目解析:2<=n<2^54,如果n是素数直接输出,否则求N的最小质因数. 求大整数最小质因数的算法没看懂,不打算看 ...

  6. POJ1811_Prime Test【Miller Rabin素数測试】【Pollar Rho整数分解】

    Prime Test Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 29193 Accepted: 7392 Case Time ...

  7. Miller-Rabin​素数测试算法

    \(Miller-Rabin\)​素数测试 用途 判断整数\(n\)是否是质数,在\(n\)较小的情况下,可以使用试除法,时间复杂度为\(O(\sqrt n)\).但当\(n\)的值较大的时候,朴素的 ...

  8. 素数测试算法(基于Miller-Rabin的MC算法) // Fermat素数测试法

    在以往判断一个数n是不是素数时,我们都是采用i从2到sqrt(n)能否整除n.如果能整除,则n是合数;否则是素数.但是该算法的时间复杂度为O(sqrt(n)),当n较大时,时间性能很差,特别是在网络安 ...

  9. Miller Rabin素数检测

    #include<iostream> #include<cstdio> #include<queue> #include<cstring> #inclu ...

  10. Miller-Rabbin随机性素数测试算法

    //**************************************************************** // Miller_Rabin 算法进行素数测试 //速度快,而且 ...

随机推荐

  1. 【博客搭建】Typecho个人博客搭建,快速安装,超小白(很简单的)

    使用Typecho框架一个月又十二天了,就目前感觉来说,整体还不错,很多方面都支持个性化,二次开发,但是目前MD编辑器有一丢丢问题,不能同步滚动条滚动,就是编辑器区域滚动,预览区域没有动静,需要两边都 ...

  2. 论TEMP临时变量与VAR静态变量区别

    TEMP临时变量:顾名思义,这种变量类型是临时的,没有固定的存放数据的内存空间.每次扫描结束后则清零,在下个扫描周期开始时,这个变量的值都是不确定的,一般为0.使用临时变量需要遵循一个原则:先赋值再使 ...

  3. CRM【第一篇】: 权限组件之权限控制

    1. 问:为什么程序需要权限控制? 答:生活中的权限限制,① 看灾难片电影<2012>中富人和权贵有权登上诺亚方舟,穷苦老百姓只有等着灾难的来临:② 屌丝们,有没有想过为什么那些长得漂亮身 ...

  4. JavaScript动画实例:动感小球

    已知圆的坐标方程为: X=R*SIN(θ) Y=R*COS(θ)     (0≤θ≤2π) 将0~2π区间等分48段,即设定间隔dig的值为π/24.θ初始值从0开始,按曲线方程求得坐标值(x,y), ...

  5. MySQL 三万字精华总结 + 面试100 问,吊打面试官绰绰有余(收藏系列)

    写在之前:不建议那种上来就是各种面试题罗列,然后背书式的去记忆,对技术的提升帮助很小,对正经面试也没什么帮助,有点东西的面试官深挖下就懵逼了. 个人建议把面试题看作是费曼学习法中的回顾.简化的环节,准 ...

  6. TortoiseGit 解决冲突的两种方法

    一.冲突发生原因: 用户A 有新提交 用户B 没有pull, 写新代码 ,pull , 提示有冲突   Solution: 1: stash save(把自己的代码隐藏存起来) -> 重新pul ...

  7. Cyber Security - Palo Alto Security Policies(2)

    Task 3 The SOC(Security Operation Center) monitoring team dashboard reported more 1,000 requests to ...

  8. jupyter中%matplotlib inline报错

    学习matplotlib时,使用的jupyter跑代码.报错如上图.大致就是后面的注释不能被识别.我寻思着注释不用识别吧,大概是因为%后跟的语句被全部当成命令行执行了,然后命令行不识别行内注释,导致报 ...

  9. kubernetes+Azure DevOps实现.Net Core项目的自动化部署&均衡负载

    1. 前言 2. Net Core项目本身的准备 2.1 dockerfile 2.2 创建kubernetes用于helm的chart包 2.2.1 说明 2.2.2 chart文件目录和文件组成 ...

  10. Linux内核功能介绍及如何使用保护您的网页安全

    在本文中,我们快速浏览了Linux内核的许可流程,并向您展示了如何使用它们来保护您的网页或应用安全 传统上,Linux内核通过以下两类来区分其进程: 特权进程:这些进程使用户可以绕过所有内核权限检查. ...