使用Fermat小定理(Fermat's little theorem)的原理进行测试,不满足 \(2^{n-1}\;\mod\;n\;=\;1\) 的n一定不是质数;如果满足的话则多半是质数,满足上式(通过2为底的Fermat小定理测试)且是合数的,被称为“伪质数”(pseudoprime number),一个简单的伪质数是341。一个合数可能在a=2时通过了测试,但a=3时的计算结果却排除了素数的可能。于是,人们扩展了伪素数的定义,称满足 \(a^{n-1}\;\mod\;n\;=\;1\) 的合数n叫做以a为底的伪素数(pseudoprime to base a)。前1e9个自然数中同时以2和3为底的伪素数只有1272个,这告诉我们如果同时验证a=2和a=3两种情况,算法出错的概率降到了0.000025。容易想到,选择用来测试的a越多,算法越准确。通常我们的做法是,随机选择若干个小于待测数的正整数作为底数a进行若干次 测试,只要有一次没有通过测试就立即把这个数扔回合数的世界。这就是Fermat素性测试(直接使用Fermat小定理进行测试)。

如果考虑了所有小于n的底数a,出错的概率也不能降到0。Carmichael第一个发现这样极端的伪素数,他把它们称作Carmichael数。第一个Carmichael数小得惊人,仅仅是一个三位数,561。前10亿个自然数中Carmichael数也有600个之多。Carmichael数的存在说明,我们还需要继续加强素性判断的算法。

Miller和Rabin两个人的工作让Fermat素性测试迈出了革命性的一步,建立了Miller-Rabin素性测试算法。新的测试基于下面的定理:

如果p是质数,x是小于p的正整数,且 \(x^2\;\mod\;p\;=\;1\) ,那么要么 \(x=1\) ,要么 \(x=p-1\) 。这是显然的,因为 \(x^2\;\mod\;p\;=\;1\) 相当于 \(p|x^2-1\) ,也即\(p|(x+1)(x-1)\)。由于p是质数,那么只可能是 \(x-1\) 能被 \(p\) 整除(此时 \(x=1\) )或 \(x+1\) 能被 \(p\) 整除(此时 \(x=p-1\) )。

我们下面来演示一下上面的定理如何应用在Fermat素性测试上。前面说过341可以通过以2为底的Fermat测试,因 为2^340 mod 341=1。如果341真是素数的话,那么2^170 mod 341只可能是1或340;当算得2^170 mod 341确实等于1时,我们可以继续查看2^85除以341的结果。我们发现,2^85 mod 341=32,这一结果摘掉了341头上的素数皇冠,面具后面真实的嘴脸显现了出来,想假扮素数和我的素MM交往的企图暴露了出来。
这就 是Miller-Rabin素性测试的方法。不断地提取指数n-1中的因子2,把n-1表示成d*2^r(其中d是一个奇数)。那么我们需要计算的东西就 变成了a的d*2^r次方除以n的余数。于是,a^(d * 2^(r-1))要么等于1,要么等于n-1。如果a^(d * 2^(r-1))等于1,定理继续适用于a^(d * 2^(r-2)),这样不断开方开下去,直到对于某个i满足a^(d * 2^i) mod n = n-1或者最后指数中的2用完了得到的a^d mod n=1或n-1。这样,Fermat小定理加强为如下形式:
尽可能提取因子2, 把n-1表示成d*2^r,如果n是一个素数,那么或者a^d mod n=1,或者存在某个i使得a^(d*2^i) mod n=n-1 ( 0<=i<r ) (注意i可以等于0,这就把a^d mod n=n-1的情况统一到后面去了)
Miller-Rabin 素性测试同样是不确定算法,我们把可以通过以a为底的Miller-Rabin测试的合数称作以a为底的强伪素数(strong pseudoprime)。第一个以2为底的强伪素数为2047。第一个以2和3为底的强伪素数则大到1 373 653。

对 于大数的素性判断,目前Miller-Rabin算法应用最广泛。一般底数仍然是随机选取,但当待测数不太大时,选择测试底数就有一些技巧了。比如,如果 被测数小于4 759 123 141,那么只需要测试三个底数2, 7和61就足够了。当然,你测试的越多,正确的范围肯定也越大。如果你每次都用前7个素数(2, 3, 5, 7, 11, 13和17)进行测试,所有不超过341 550 071 728 320的数都是正确的。如果选用2, 3, 7, 61和24251作为底数,那么10^16内唯一的强伪素数为46 856 248 255 981。这样的一些结论使得Miller-Rabin算法在OI中非常实用。通常认为,Miller-Rabin素性测试的正确率可以令人接受,随机选取 k个底数进行测试算法的失误率大概为4^(-k)。

有一个小技巧可以避免溢出,方法就是乘法改为加法,把上面的代码:

参考资料:

素数与素性测试(Miller-Rabin测试) - Norlan - 博客园

(https://www.cnblogs.com/Doggu/p/MillerRabin_PollardRho.html)

模板 - 数学 - 数论 - Miller-Rabin算法的更多相关文章

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

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

  2. Miller Rabin 算法简介

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

  3. Miller Rabin算法详解

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

  4. 数学--数论---P4718 Pollard-Rho算法 大数分解

    P4718 [模板]Pollard-Rho算法 题目描述 MillerRabin算法是一种高效的质数判断方法.虽然是一种不确定的质数判断法,但是在选择多种底数的情况下,正确率是可以接受的.Pollar ...

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

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

  6. Miller Rabin算法学习笔记

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

  7. 算法模板の数学&数论

    1.求逆元 int inv(int a) { ) ; return (MOD - MOD / a) * inv(MOD % a); } 2.线性筛法 bool isPrime[MAXN]; int l ...

  8. (Miller Rabin算法)判断一个数是否为素数

    1.约定 x%y为x取模y,即x除以y所得的余数,当x<y时,x%y=x,所有取模的运算对象都为整数. x^y表示x的y次方.乘方运算的优先级高于乘除和取模,加减的优先级最低. 见到x^y/z这 ...

  9. 模板 - 数学 - 数论 - 扩展Euler定理

    费马(Fermat)小定理 当 \(p\) 为质数,则 \(a^{p-1}\equiv 1 \mod p\) 反之,费马小定理的逆定理不成立,这样的数叫做伪质数,最小的伪质数是341. 欧拉(Eule ...

随机推荐

  1. ADO.NET 六(DataRow DataColumn)

    已经介绍了使用 SqlCommand 对象中的 ExecuteNonQuery 方法执行非查询 SQL 语句来实现对数据表的更新操作,使用 DataSet 对象也能实现相同的功能, 并且能节省数据访问 ...

  2. bat 设置多个静态ip

    @echo off REM 本地连接名称 set NetName="本地连接 2" REM 默认IP netsh interface ipv4 set address name=% ...

  3. sql server 获取某一字段分组数据的前十条记录

    1.sql 语法 select m, n from ( select row_number () over (partition by m order by n desc) rn,--以m分组,分组内 ...

  4. Winmanager,NERDTree和MiniBufExplorer

    NERDTree树形浏览文件 MiniBufExplorer多文件同时编辑 Winmanager将NERDTree和MiniBufExplorer界面整合 下载 http://www.vim.org/ ...

  5. DRF 筛选

    from rest_framework.generics import ListAPIView,CreateAPIView,UpdateAPIView,RetrieveAPIView,DestroyA ...

  6. Android自动化测试探索(一)adb详细介绍

    adb详细介绍 #1. 基本简介 adb,即Android Debug Bridge,它是Android开发/测试人员不可替代的强大工具 #2. Mac上安装adb 安装brew /usr/bin/r ...

  7. python之PEP8规范

    比较需要注意的 缩进 每一级缩进使用4个空格. 续行应该与其包裹元素对齐,要么使用圆括号.方括号和花括号内的隐式行连接来垂直对齐,要么使用挂行缩进对齐3.当使用挂行缩进时,应该考虑到第一行不应该有参数 ...

  8. Nginx配置文件示例

    Nginx的配置文件示例:(仅供参考) 强烈建议先将默认的配置文件备份再进行操作! 请根据自己项目的实际路径来配置相关路径! uwsgi配置文件请参考:uwsgi配置文件示例 # For more i ...

  9. MySQL JOIN原理(转)

    先看一下实验的两张表: 表comments,总行数28856 表comments_for,总行数57,comments_id是有索引的,ID列为主键. 以上两张表是我们测试的基础,然后看一下索引,co ...

  10. Kubernetes+Federation打造跨多云管理服务

    Kubernetes日渐普及,在公有云.私有云等多个环境中部署kubernetes集群已是常规做法,而随着环境的复杂多样和集群数量增长,如何高效地管理这些集群成为新的问题.于是跨多云管理服务应运而生. ...