前言

素数判定?

小学生都可以打的出来!

直接暴力O(n)O(\sqrt n)O(n​)……

然后就会发现,慢死了……

于是我们想到了筛法,比如前几天说到的詹欧筛法

但是线性的时间和空间成了硬伤……如果是long long范围内的数,就搞不出来了。

那么素数判定就止步于此了吗?

不可能的,优化永无止境。我们可以用正确率来换时间啊!

Miller-Rabbin素数判定法就是这样的一个水法好方法。


前置数论知识

“费马小定理的逆定理”

首先是人人皆知的费马小定理:如果ppp为素数,对于任意非零整数aaa,满足ap−1≡1(mod  p)a^{p-1}\equiv 1(\mod p)ap−1≡1(modp)

怎么证明呢?抱歉,我初三了也不会证……(WHH五年级时就会证了……)

接下来有个猜想,如果有个正整数ppp,满足对于任意aaa,有ap−1≡1(mod  p)a^{p-1}\equiv 1(
\mod p)ap−1≡1(modp),那么ppp是素数。

这个猜想是正确的吗?

当然不是……

有种可恶的数叫Carmichael数,你可以将它称为伪素数

这种恶心的数啊,它不是素数,但是它满足这条性质。

它的个数是无限的,但是分布很稀疏,在10810^8108内,只有255255255个Carmichael数。

所以正确率还是很高的……

可是我们要精益求精,并且,要知道这个世界上有很多毒瘤出题人……有时候数据怎样不取决于你的运气,全在于出题人……

二次探测定理

为了提高上面那东西的正确率,MillerMillerMiller和RabbinRabbinRabbin决定引入二次探测定理。

定理内容很简单:若ppp是一个素数,方程x2≡1(mod  p)x^2\equiv 1(\mod p)x2≡1(modp)的唯二解为p=±1(mod  p)p=\pm1(\mod p)p=±1(modp)

证明?

移项得x2−1≡0(mod  p)x^2-1\equiv 0(\mod p)x2−1≡0(modp),

所以(x−1)(x+1)≡0(mod  p)(x-1)(x+1)\equiv 0 (\mod p)(x−1)(x+1)≡0(modp)

所以p∣(x+1)(x−1)p \mid (x+1)(x-1)p∣(x+1)(x−1)

因为ppp是个素数,所以p∣(x+1)p \mid (x+1)p∣(x+1)或p∣(x−1)p \mid (x-1)p∣(x−1)

所以x=±1(mod  p)x=\pm1(\mod p)x=±1(modp)

我们反过来看,如果存在非零整数xxx使得这个定理不成立,那么ppp一定是合数。

所以这个东西可以大大地加强正确率。


Miller-Rabbin素数判定

这个算法就是将上面两个数论知识结合起来。

对于待测数ppp,先将p−1p-1p−1分解成2kt2^kt2kt的形式,其中ttt为奇数。

然后取几个基数aaa,分别做以下操作:

首先算出ata^tat,判断它是否为±1\pm1±1,如果是,则暂时判定为素数,退出。(这样它在经过自乘后会保持111,满足性质)

如果不是,就枚举t−1t-1t−1次,不断自乘,判断他是否为−1-1−1,如果是,则暂时判定为素数,退出。(原因类似,不用判断111,因为如果它是111,在之前必定是±1\pm 1±1,早就退出了)

搞完之后,如果之前没有退出,那么就将它判定为合数(再自乘一次就变成ap−1a^{p-1}ap−1,由于前面不是±1\pm1±1,所以一定不成立),退出。

所有基数计算完毕,如果判定为素数,就返回素数。

可以想象一下,从一个杂乱的数,变成−1-1−1,再变成111,后面都是111。

具体可以见代码。超短,特别好理解。


如何拥有更高的正确率?

前面说过Miller_Rabbin是牺牲正确性的算法。

所以基数的取值会和程序的效果有很大关系。

一般来说,可以取一堆随机数,这样就可以达到很高的正确率了。

但是我们要精益求精。

有一种方法是取前几个素数:



图片截自64位以内Rabin-Miller_强伪素数测试和Pollard_rho_因数分解算法的实现.doc

假如选取素数2 3 5 7,在2.5∗10132.5*10^{13}2.5∗1013内唯一一个强伪素数为3,215,031,7513,215,031,7513,215,031,751。

假如选取素数2 3 7 61 24251,在101410^{14}1014内唯一一个强伪素数为46,856,248,255,98146,856,248,255,98146,856,248,255,981。

背下来就可以了……(以防毒瘤出题人)

我脑子不好,所以枚举前面的几个素数。

虽然说Miller_Rabbin牺牲了正确率,但是在一定范围内,只要你的基数取得好,那么正确率是可以达到100%100\%100%的。

还有在判定之前,先拿几个素数来判一下,判完再走。前面的777个素数可以判掉81.9%81.9\%81.9%的数。

当然不要判太多,判越多次,比起先前贡献的增长就越小。


代码

代码比较简单,主体部分很短。

记得配上快速幂和龟速乘,不然会爆炸。

long long mul(long long a,long long b,long long mo){
long long res=0;
for (;b;b>>=1,a=(a<<1)%mo)
if (b&1)
res=(res+a)%mo;
return res;
}
inline long long mpow(long long x,long long y,long long mo){
long long res=1;
for (;y;y>>=1,x=mul(x,x,mo))
if (y&1)
res=mul(res,x,mo);
return res;
}
const int p[7]={2,3,5,7,11,13,17};
inline bool mr(long long x){
if (x==0 || x==1)
return 0;
for (int i=0;i<7;++i){
if (x==p[i])
return 1;
if (!(x%p[i]))
return 0;
}
int k=0;
long long y=x-1;
while (!(y&1))
y>>=1,++k;
for (int i=0;i<7;++i){
long long s=mpow(p[i],y,x);
if (s==1 || s==x-1)
continue;
for (int j=1;j<k;++j){
s=mul(s,s,x);
if (s==x-1)
break;
}
if (s!=x-1)
return 0;
}
return 1;
}

Miler-Rabbin素数判定的更多相关文章

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

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

  2. HDOJ2012素数判定

    素数判定 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

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

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

  4. Codevs 1702 素数判定 2(Fermat定理)

    1702 素数判定 2 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 传送门 题目描述 Description 一个数,他是素数么? 设他为P满足(P< ...

  5. hdu 2012 素数判定 Miller_Rabbin

    素数判定 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  6. 素数判定 AC 杭电

    素数判定 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  7. 杭电ACM 素数判定

    素数判定 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

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

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

  9. 多项式求和,素数判定 HDU2011.2012

    HDU 2011:多项式求和 Description 多项式的描述如下: 1 - 1/2 + 1/3 - 1/4 + 1/5 - 1/6 + ... 现在请你求出该多项式的前n项的和.   Input ...

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

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

随机推荐

  1. c++11新特性学习2

    noexcept 替代 throw.优点是更安全, 如果noexcept 修饰的函数抛出了异常,编辑器可以直接选择终止程序. C++ 11中析构函数默认为noexcept(true),从而阻止异常的扩 ...

  2. (转)元类metaclass

    阅读目录 一 前言 二 什么是元类 三 class关键字创建类的流程分析 五 自定义元类控制类OldboyTeacher的创建 六 自定义元类控制类OldboyTeacher的调用 六 再看属性查找 ...

  3. selenium+python 绕过登录进行测试

    多个Py文件进行多线程测试时,每次登录是很麻烦的事情,所以通过cookie登录,可以绕过登录操作      但是至少需要正常登录一次才能获取到cookie 然后使用cookies进行登录

  4. 活动:新春第一次送书,价值78元 X 3本

    新春第一次送书活动,送出3本重量级书籍<深入分布式缓存:从原理到实践>. 作者介绍: 于君泽:蚂蚁金服高级技术专家.花名右军,IT从业超过十五年.对高并发.分布式架构.内建质量.研发管理有 ...

  5. beautifulsoup的使用

    解析库 解析器 使用方法 优势 劣势 Python标准库 BeautifulSoup(markup, "html.parser") Python的内置标准库.执行速度适中 .文档容 ...

  6. 如何使用Hive集成Solr?

    (一)Hive+Solr简介 Hive作为Hadoop生态系统里面离线的数据仓库,可以非常方便的使用SQL的方式来离线分析海量的历史数据,并根据分析的结果,来干一些其他的事情,如报表统计查询等. So ...

  7. kafka 入门

    李克华 云计算高级群: 292870151 195907286 交流:Hadoop.NoSQL.分布式.lucene.solr.nutch  kafka入门:简介.使用场景.设计原理.主要配置及集群搭 ...

  8. 笔记:Python防止SQL注入

    非安全的方式,使用动态拼接SQL 输入' or 1 = 1 or '1 sql ="""SELECT * FROM goods WHERE name = '%s';&qu ...

  9. JS对象 四舍五入round() round() 方法可把一个数字四舍五入为最接近的整数。 语法: Math.round(x)

    四舍五入round() round() 方法可把一个数字四舍五入为最接近的整数. 语法: Math.round(x) 参数说明: 注意: 1. 返回与 x 最接近的整数. 2. 对于 0.5,该方法将 ...

  10. 前端常用的库和实用技术之JavaScript多线程

    多线程概念: 多线程是指从软件或硬件上实现多个线程并发执行的技术.具有多线程能力的计算机因有硬件支持而能够在 同一时间执行多于一个线程,进而提升整理处理性能.具有这种能力的系统包括对称多处理机,多核心 ...