适用范围:较大数的较快素性判断

思路:

因为有好的文章讲解具体原理(见参考文章),这里只是把代码的大致思路点一下,读完了文章如果还有些迷糊,可以参考以下解释

原理是费马小定理:如果p是素数,则a^(p-1)%p==1,加上二次探测定理:如果p是一个素数,则x^2%p==1的解为,则x=1或者x=n-1。

因为有通过费马小定理的伪素数的概率不是充分小,在此基础上加以改进判断。

一次检测中:

主要是把一个数n的n-1分解成d*2^r的形式,其中d为奇数,正向过程是a^n%p如果是1,就继续分解a^(n/2)%p,(a为一个与n互素的数)看是否为1,;如果是n-1就停止分解,说明至此无法判断是否为素数;如果不等于这两个值,则一定为合数。而在写代码过程是这个过程的逆向过程,先分解到底,看最后这个a^d%p是否为1或n-1,如果是说明已经分解到底了,也就是通过了此次素性测试。如果不是,说明在正向过程中出现了要么a的某次方为n-1,根据算法停止了检测过程;要么就是中间的某一个结果不等于这两个数,那么就是合数。就从最后往前面推,每一步看满不满足上述条件。直到判断为合数或者终止检测的那一步。

多次检测过程:

不停更换a测试。

代码:(代码中可能需要用到快速幂和大数乘积取余,可以参考前一篇博客)

 #include <iostream>
#include <time.h>
using namespace std;
long long an[] = {,,,,,,,};
long long Random(long long n)//生成0到n之间的整数
{
return (double) rand()/RAND_MAX*n+0.5;//(doubel)rand()/RAND_MAX生成0-1之间的浮点数
}
long long q_mod(long long a,long long n,long long p)
{
a = a%p;
//首先降a的规模
long long sum = ;//记录结果
while(n)
{
if(n&)
{
sum = (sum*a)%p;//n为奇数时单独拿出来乘
}
a = (a*a)%p;//合并a降n的规模
n /= ;
}
return sum;
}
long long q_mul(long long a,long long b,long long p)
{
long long sum = ;
while(b)
{
if(b&)//如果b的二进制末尾是零
{
(sum += a)%=p;//a要加上取余
}
(a <<= )%=p;//不断把a乘2相当于提高位数
b >>= ;//把b右移
}
return sum;
}
bool witness(long long a,long long n)
{
long long d = n-;
long long r = ;
while(d%==)
{
d/=;
r++;
}//n-1分解成d*2^r,d为奇数
long long x = q_mod(a,d,n);
//cout << "d " << d << " r " << r << " x " << x << endl;
if(x==||x==n-)//最终的余数是1或n-1则可能是素数
{
return true;
}
while(r--)
{
x = q_mul(x,x,n);
if(x==n-)//考虑开始在不断地往下余的过程
{
return true;//中间如果有一个余数是n-1说明中断了此过程,则可能是素数
}
}
return false;//否则如果中间没有中断但最后是余数又不是n-1和1说明一定不是素数
}
bool miller_rabin(long long n)
{
const int times = ;//试验次数
if(n==)
{
return true;
}
if(n<||n%==)
{
return false;
}
for(int i = ;i<times;i++)
{
long long a = Random(n-)+;//1到(n-1)
//cout << a << endl;
if(!witness(a,n))
{
return false;
}
}
return true;
}
int main()
{
long long num;
cin >> num;
if(miller_rabin(num))
{
cout << "Yes" << endl;
}
else
{
cout << "No" << endl;
}
}

参考文章:

Matrix67,数论部分第一节:素数与素性测试,http://www.matrix67.com/blog/archives/234(原理只推荐这一篇,这一篇是我目前见到的解释的最清晰,也可能是最精彩的,没有之一!虽然是07年的,好博客与时间没有关系)

因为上篇代码部分用的是Pascal,这里找到c++的代码版本:

StanleyClinton,素数判定Miller_Rabin算法详解,https://blog.csdn.net/maxichu/article/details/45458569

还有rand函数的使用:https://jingyan.baidu.com/article/e73e26c060bdbc24adb6a7b0.html

米勒罗宾素数检测(Miller-Rabin)的更多相关文章

  1. [SinGuLaRiTy] 米勒罗宾素数判定法

    [SinGuLaRiTy-1003] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 背景 数论学家利用费马小定理研究出了多种素数测试办法,M ...

  2. Miller Rabin算法详解

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

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

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

  4. 米勒罗宾素性测试(Miller–Rabin primality test)

    如何判断一个素是素数 效率很高的筛法 打个表 (素数的倍数一定是合数) 就可以解决问题. 筛选法的效率很高,但是遇到大素数就无能为力了. 米勒罗宾素性测试是一个相当著名的判断是否是素数的算法 核心为费 ...

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

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

  6. 与数论的厮守01:素数的测试——Miller Rabin

    看一个数是否为质数,我们通常会用那个O(√N)的算法来做,那个算法叫试除法.然而当这个数非常大的时候,这个高增长率的时间复杂度就不够这个数跑了. 为了解决这个问题,我们先来看看费马小定理:若n为素数, ...

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

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

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

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

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

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

随机推荐

  1. [Docker] 六步运行一个 sentry 实例

    # 6步, https://hub.docker.com/_/sentry/ # 依赖Redisdocker run -d --name sentry-redis redis:3.2.12 # 依赖p ...

  2. Gerrit - Gerrit与GitLab集成

    1 - 简介 虽然Gerrit 本身提供 Code Review和 Git 仓库的两大功能,但实际上很多项目用的是其他的Git仓库,例如GitLab和GitHub. 一般情况下,Gerrit位于最终代 ...

  3. winform窗口关闭,进程没有关掉的解决办法

    /// <summary> /// 窗口关闭删除所有活动线程 /// </summary> /// <param name="sender">& ...

  4. 【idea】全局搜索、替换只显示100条的问题

    没有修改之前 修改之后 如果用的是idea默认的快捷键,按Ctrl+Shift+A,然后输入Registry 如果是eclipse的快捷键

  5. 【springboot】【idea】实体类免写get、set等方法,使用lombok依赖和插件的@Data类注解

    需求,一个实体类,规范写法一定要对应的get.set方法,有必要还要重写toString方法.虽然可以快速生成get.set等方法,但是如果要添加或减少成员属性时就得重新生成get.set等方法. 而 ...

  6. 90% 前端开发者都不知道的 JavaScript 实用小技巧

    面试神器之数组去重 const a = [...new Set([1, 2, 3, 3])] >> [1, 2, 3] 操作数组担心 falsy 值? const res = myArra ...

  7. SQL Server中的GAM页和SGAM页

    简介 我们已经知道SQL Server IO最小的单位是页,连续的8个页是一个区.SQL Server需要一种方式来知道其所管辖的数据库中的空间使用情况,这就是GAM页和SGAM页. Global A ...

  8. 【转帖】HBase基本概念与基本使用

    HBase基本概念与基本使用 https://www.cnblogs.com/swordfall/p/8737328.html 分类: HBase undefined 1. HBase简介 1.1 什 ...

  9. [Linux] 在 Ubuntu 19.10 上开启 SSH 服务并允许远程登录

    在 Ubuntu 19.10 上安装 SSH,并开启服务 0.检查并确认系统当前是否已安装SSH: sudo ps -e | grep ssh 如果只有 ssh-agent 说明 ssh-server ...

  10. windows SDK中的wininet写http客户端

    BOOL InternetSetOption( _In_  HINTERNET hInternet, _In_  DWORD dwOption, _In_  LPVOID lpBuffer, _In_ ...