一、实现原理

我们以前都是怎么判断素数的呢:

试除法: 若一个正整数N为合数,则存在一个能整除N的数k,其中\(2\leqslant k \leqslant \sqrt N\)。

具体实施如下:

inline int is_prime(int n){
if(n<2) return 0;
for(int i=2;i<=sqrt(n);i++){
if(n%i==0) return 0;
}
return 1;
}

这种方法的时间复杂度为\(O(\sqrt n)\)。

现在,我们希望更快地判断一个数是否为素数。

我们可以借助费马小定理来判断:

如果p是一个质数,而整数a不是p的倍数,则有

\[a^{p-1}\equiv 1\pmod p
\]

Miller-Robbin素数判定就是基于上述定理实现的,如果我们随机枚举一个\(a\),且\(a\)满足费马小定理,那么\(p\)就是素数。所以Miller-Robbin素数判定是一种随机性算法。

需要注意的是,我们这样判断素数的方法实际上利用的是费马小定理的逆定理。不幸的是,费马小定理的逆定理并不是一个真命题。

  • 存在\(a=2,p=341\)时满足费马小定理,而\(341=11*31\)却是合数

我们把像341这样的数称作伪素数。实际上,伪素数有无穷多组。

这意味着一次判断不足以保证我们的程序正确。当然,解决这个问题也十分简单。

我们只需要重复操作大约30次,便能将正确率提升到我们期待的水平。

另外,我们使用快速幂来计算\(a^{p-1}\)。总复杂度为\(O(logn)\)。

下面给出Miller-Robbin素数判定的模板:

int qpow(int a,int b,int mod){//快速幂
int res=1;
while(b){
if(b&1) res=(res%mod*a)%mod;
a=(a%mod)*a%mod;
b>>=1;
}
return res;
}
bool query_prime(int x){
if(x==2)return true;
if(x==1)return false;
for(int i=1;i<=30;i++){
int base=rand()%(x-1)+1;//随机枚举a
if(qpow(base,x-1,x)!=1) return false;//计算a^(p-1)%p的值
}
return true;
}

二、应用

判断一个正整数是否为素数

模板题:AT807 素数、コンテスト、素数

#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int qpow(int a,int b,int mod){//快速幂
int res=1;
while(b){
if(b&1) res=(res%mod*a)%mod;
b>>=1;
a=(a%mod)*a%mod;
}
return res;
}
inline int miller_robbin(int num){//核心代码
for(int i=1;i<=30;i++){
int base=rand()%(num-1)+1;
if(qpow(base,num-1,num)!=1) return 0;
}
return 1;
}
signed main(){
int num;
scanf("%d",&num);
if(num==1){
printf("NO");
return 0;
}
miller_robbin(num)?printf("YES\n"):printf("NO\n");
return 0;
}

附赠一道水题:(主要是练习素数判定)

AT1476 素数判定

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll qpow(ll a,ll b,ll mod){
ll res=1;
while(b){
if(b&1)res=(res%mod*a)%mod;
a=(a%mod)*a%mod;
b>>=1;
}
return res;
}
bool query_prime(ll x)
{
if(x==2)return true;
if(x==1)return false;
for(int i=1;i<=30;i++){
ll base=rand()%(x-1)+1;
if(qpow(base,x-1,x)!=1)return false;
}
return true;
}
int main()
{
srand(time(NULL));
ll num;
scanf("%lld",&num);
if(query_prime(num)||(num%2!=0&&num%3!=0&&num%5!=0&&num!=1))printf("Prime\n");
else printf("Not Prime\n");
return 0;
}

三、小结

使用Miller-Robbin素数判定,我们可以将复杂度降低至\(O(logn)\)级别(常数阶可以被忽略)。这样比原来的方法会快很多。


[算法]Miller-Robbin素数判定的更多相关文章

  1. Miller-Rabin算法 codevs 1702 素数判定 2

    转载自:http://www.dxmtb.com/blog/miller-rabbin/ 普通的素数测试我们有O(√ n)的试除算法.事实上,我们有O(slog³n)的算法. 定理一:假如p是质数,且 ...

  2. HDU2138 素数判定

    HDU2138 给定N个32位大于等于2的正整数 输出其中素数的个数 用Miller Rabin 素数判定法 效率很高 数学证明比较复杂,略过, 会使用这个接口即可. #include<iost ...

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

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

  4. 数学#素数判定Miller_Rabin+大数因数分解Pollard_rho算法 POJ 1811&2429

    素数判定Miller_Rabin算法详解: http://blog.csdn.net/maxichu/article/details/45458569 大数因数分解Pollard_rho算法详解: h ...

  5. 10^9以上素数判定,Miller_Rabin算法

    #include<iostream> #include<cstdio> #include<ctime> #include<string.h> #incl ...

  6. 公钥密码之RSA密码算法大素数判定:Miller-Rabin判定法!

    公钥密码之RSA密码算法大素数判定:Miller-Rabin判定法! 先存档再说,以后实验报告还得打印上交. Miller-Rabin大素数判定对于学算法的人来讲不是什么难事,主要了解其原理. 先来灌 ...

  7. Miller_Rabin()算法素数判定 +ollard_rho 算法进行质因数分解

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

  8. FZU 1649 Prime number or not米勒拉宾大素数判定方法。

    C - Prime number or not Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & % ...

  9. algorithm@ 大素数判定和大整数质因数分解

    #include<stdio.h> #include<string.h> #include<stdlib.h> #include<time.h> #in ...

随机推荐

  1. Spring Cloud 系列之 Netflix Hystrix 服务监控

    Actuator Hystrix 除了可以实现服务容错之外,还提供了近乎实时的监控功能,将服务执行结果和运行指标,请求数量成功数量等等这些状态通过 Actuator 进行收集,然后访问 /actuat ...

  2. mysql查询性能问题,加了order by速度慢了

    关于order by的查询优化可以看一下: MySQL ORDER BY/LIMIT performance: late row lookups 主要介绍了两个方法: 第一个是FORCE INDEX ...

  3. CORS 跨域中的 preflight 请求

    我们知道借助Access-Control-Allow-Origin响应头字段可以允许跨域 AJAX, 对于非简单请求,CORS 机制跨域会首先进行 preflight(一个 OPTIONS 请求), ...

  4. 记一次phpstudy应急响应

    某日,销售接了一个电话,突然告诉我有个某单位服务器中了木马被黑,具体情况未知.由于客户那边比较急,于是我火速赶往客户现场.到现场,客户首先给我看了深信服防火墙拦截记录,显示内网三台机器被入侵.通过沟通 ...

  5. JMM内存模型、CPU缓存一致性原则(MESI)、指令重排、as-if-serial、happen-before原则

    JMM三大特性原子性 汇编指令 --原子比较和交换在底层的支持 cmp-chxg 总线加锁机制 Synchronized Lock锁机制 public class VolatileAtomicSamp ...

  6. javascript异步上传图片文件

    html: <form action="url" enctype="multipart/form-data" id="myform"  ...

  7. 8千字干货教程|java反射精讲

    java反射机制精讲 目录 1. 反射机制的概念 2. 反射的基础Class类 3. 反射的用法 4. 反射的应用示例 作者简介:全栈学习笔记,一个正在努力的人 微信公众号:公众号日更,精彩美文每天推 ...

  8. 数据科学中需要知道的5个关于奇异值分解(SVD)的应用

    介绍 "Another day has passed, and I still haven't used y = mx + b." 这听起来是不是很熟悉?我经常听到我大学的熟人抱怨 ...

  9. python3读取excel实战

    '''参数化'''import xlrd,xlwt,jsonfrom api实现.读取参数化接口说明 import TestApiclass ReadFileData: def __init__(se ...

  10. ATM购物车+三层结构项目设计

    ATM购物车项目 模拟实现一个ATM + 购物商城程序. 该程序实现普通用户的登录注册.提现充值还款等功能,并且支持到网上商城购物的功能. 账户余额足够支付商品价格时,扣款支付:余额不足时,无法支付, ...