看一个数是否为质数,我们通常会用那个O(√N)的算法来做,那个算法叫试除法。然而当这个数非常大的时候,这个高增长率的时间复杂度就不够这个数跑了。

  为了解决这个问题,我们先来看看费马小定理:若n为素数,a与n互质,则an-1Ξ1(mod n)。于是有人想过把它倒过来判断n是否为素数。首先,若a与n不互质,那么n为合数。所以只需要满足an-1Ξ1(mod n)即可,这个a干脆就让它等于2了。即判断2n-1Ξ1(mod n)是否成立。若不成立,那么n必定为合数。但成立时n就是素数吗?又有人找出了个数:2340Ξ1(mod 341),但是发现341是合数(11*31)。那我们能不能直接把a换成另一个数呢?答案是否定的。因为对于所有a,都存在an-1Ξ1(mod n),其中n为合数。于是这个方法就出错了。但是紧接着Miller Rabin测试对这个方法进行了改进。

  Miller Rabin的依据是,当n为素数时,x2Ξ1(mod n)的根有两个:x=1和x=n-1。这个根叫做平凡平方根(真的拗口)。因此,如果对于模n存在1的非平凡平方根,则n是个合数。

  那么Miller Rabin怎么改进的呢?

    ①选取多个基数a;

    ②寻找模n为1的非平凡平方根:令2t*u=n-1(t>=1,u为奇数),则an-1=a2t*u=(au)2t。先算出x=au mod n,再把x平方t次,每次模上n,这样我们就得到了一个长度为t+1的序列。我们希望这个序列以1结尾,并且若某一项为1,则前一项必须为1或n-1,否则n就是合数。

  这并不是简单地验证一下费马小定理。Miller Rabin会对一个数进行s次测试,其出错率低至2-s

  然后是代码(喜人的rand):

#include <cstdio>
#include <cstdlib>
#include <ctime>
using namespace std; inline long long pow(long long a, long long b, long long p){
long long ans = % p;
while(b){
if(b & ) ans = ans * a % p;
a = a * a % p;
b >>= ;
}
return ans;
} inline bool judge(long long n, long long a){
long long u = , t = n - ;
while(t % == ) u++, t /= ;
long long x = pow(a, t, n);
for(long long i = ; i <= u; i++){
long long next = x * x % n;
if(next == && x != && x != n - ) return true;
x = next;
}
return x == ? false : true;
} inline bool rabin(long long n){
if(n == ) return true;
if(n < || n % == ) return false;
for(long long i = ; i <= ; i++){
long long a = rand() % (n - ) + ;
if(judge(n, a)) return false;
}
return true;
} int main(){
srand(time());
long long t, in;
scanf("%lld", &t);
while(t--){
scanf("%lld", &in);
printf("%s\n", rabin(in) ? "yes" : "no");
}
return ;
}

  据说重庆OI出过一道Miller Rabin的题。

  总结:

    要点1.Miller Rabin是将费马小定理倒转过来,验证n是否存在非平凡平方根.

    要点2.平凡平方根:x2Ξ1(mod n),x=1或x=n-1

    要点3.对于基数a的判断基于倍增的思想.

与数论的厮守01:素数的测试——Miller Rabin的更多相关文章

  1. 关于素数:求不超过n的素数,素数的判定(Miller Rabin 测试)

    关于素数的基本介绍请参考百度百科here和维基百科here的介绍 首先介绍几条关于素数的基本定理: 定理1:如果n不是素数,则n至少有一个( 1, sqrt(n) ]范围内的的因子 定理2:如果n不是 ...

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

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

  3. Miller Rabin 大素数测试

    PS:本人第一次写随笔,写的不好请见谅. 接触MillerRabin算法大概是一年前,看到这个算法首先得为它的神奇之处大为赞叹,竟然可以通过几次随机数据的猜测就能判断出这数是否是素数,虽然说是有误差率 ...

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

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

  5. 与数论的厮守02:整数的因子分解—Pollard_Rho

    学Pollard_Rho之前,你需要学会:Miller Rabin. 这是一个很高效的玄学算法,用来对大整数进行因数分解. 我们来分解n.若n是一个素数,那么就不需要分解了.所以我们还得能够判断一个数 ...

  6. 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 ...

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

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

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

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

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

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

随机推荐

  1. spring源码:学习线索

    一.spring xml配置(不包括AOP,主要了解在初始化及实例化过程中spring配置文件中每项内容的具体实现过程,从根本上掌握spring) <bean>的名字 &,alia ...

  2. WebStorm Chinese Language Pack(中文语言包

    https://github.com/ewen0930/WebStorm-Chinese http://ewen0930.github.io/2016/04/webstorm-chinese-lang ...

  3. 前端Js框架 UI框架汇总 特性 适用范围 选择

    身为一个资深后端工程师,面对层出不穷的前端框架,总让人眼花缭乱,做一个综合解析贴,从全局着眼,让我们明白各种前端框架的应用范围,为如何选择前端框架,从不同的维度提供一些线索,做为一个长期优化贴,欢迎指 ...

  4. mysql 表分区技术

    表分区,是指根据一定规则,将数据库中的一张表分解成多个更小的,容易管理的部分.从逻辑上看,只有一张表,但是底层却是由多个物理分区组成. 表分区有什么好处: a.分区表的数据可以分布在不同的物理设备上, ...

  5. Ubuntu命令行快捷启动Matlab

    转载:https://blog.csdn.net/striker_v/article/details/52884485 Matlab R2015b默认安装目录/usr/local/MATLAB/R20 ...

  6. js和jquery获取textarea输入的内容

    document.getElementById('textarea').value; $("#textarea").val()

  7. Qt中关于QMouseEventbuttons()和QMouseEventbutton()的使用注意

    在进行QT程序开发中经常需要响应鼠标事件,在QWidget或QMainWindow的子类中可以重载如下鼠标事件实现自己需要的效果. virtual void mouseDoubleClickEvent ...

  8. vim 撤销 回退操作

    在vi中按u可以撤销一次操作 u   撤销上一步的操作Ctrl+r 恢复上一步被撤销的操作 注意:如果你输入“u”两次,你的文本恢复原样,那应该是你的Vim被配置在Vi兼容模式了.重做如果你撤销得太多 ...

  9. Spring framewrok 源码概览

    关于Spring 框架阅读记录 关于SpringMvc 框架阅读记录 1.首先看一个 spring-web 项目 项目结构 http 包 主要存储 http 相关信息 HttpRequst,HttpS ...

  10. 【node】mongoose的基本使用

    1.安装mongoose npm install mongoose 2.启动数据库 mongod --dbpath d:\data\db 3.引入mongoose模块并连接数据库 const mong ...