Miller-Rabin素数检测算法 acm模板
Miller-Rabin素数检测算法
其基于以下两个定理。
- Fermat小定理 
 若n是素数,则∀a(a̸≡0(modn))\forall a(a \not\equiv 0 \pmod{n})∀a(a̸≡0(modn)),有an−1≡1(modn)a^{n-1} \equiv 1 \pmod{n}an−1≡1(modn).
- 二次探测定理 
 若n是素数,则x2≡1(modn)x^2 \equiv 1 \pmod{n}x2≡1(modn)只有平凡根x=±1x=\pm1x=±1,即x=1,x=n−1x=1,x=n-1x=1,x=n−1.
费马小定理鼎鼎有名,而二次探测定理由ZpZ_pZp是域,域中无零因子容易得到。
注意这两个定理都是叙述了素数的必要条件,而Miller-Rabin对于要检验的n,是选取若干个a,检验是否满足这两个必要条件。显然,如果某个必要条件不满足,那么断言不是素数是正确的。但是,选了好几个a,都满足这两个必要条件,n是质数还是合数是无法确定的,但是Miller-Rabin算法选择忽略这一点,直接断言n是素数。
换句话说,Miller-Rabin算法断言一个数不是素数一定是正确的,断言一个数是素数,则可能是错误的。但是,实际上,会被误判为素数的合数,是很少的。而且每选取一个符合条件的a,通过检验出错的概率不超过12\frac{1}{2}21.因此实际应用中使用Miller-Rabin算法是可行的。
实际上,选取一个a,仅仅基于费马小定理给出的必要条件做断言的检测算法,被错误断言为素数的合数称作基于a的伪素数。
而通过选取各个符合条件的a,仅仅基于费马小定理,进行断言的检测算法,被错误断言为素数的伪素数就是卡迈克尔数。
具体算法
假设nnn是奇数,令n=m×2q(q≥1)n=m \times 2^q (q \geq 1)n=m×2q(q≥1),其中mmm是奇数.
对于序列am mod n,a2m mod n,a4m mod n,…,a2q×m mod na^m \bmod n, a^{2m} \bmod n, a^{4m} \bmod n,\ldots,a^{2^q \times m} \bmod nammodn,a2mmodn,a4mmodn,…,a2q×mmodn.
最后一项就是费马小定理中的an−1a^{n-1}an−1, 并且每一项都是前一项的平方。
我们一项一项往后计算。
- 若当前项为1,后面每一项显然都是1。而根据二次探测定理,n是素数必须前面一项是1或n-1.如果不符合,断言不是素数;符合,断言是素数。 
- 若当前项不是1,暂时不断言,接着往后算。除非当前是最后一项了,那么断言不是素数。 
当然,如果第一项是1,由于不存在二次探测的方程,所以不检验前面一项(或者认为前面一项符合条件)。
Code
使用了快速幂模和快速幂加模板mod_sys。下面代码只是miller-rabin核心代码。
 // 如果只是int范围内,可以将pow_v2改为pow,mlt改为普通乘法
 bool miller_rabin(ll a, ll n, ll q, ll m, mod_sys& mod) {
     a = mod.pow_v2(a, m);
     bool is_ordinary = true;
     for (int i = 0; i < q; ++i) {
         if (a == 1) {
             return is_ordinary;
         } else {
             is_ordinary = (a == n-1);
             a = mod.mlt(a,a);
         }
     }
     return (a==1)&&(is_ordinary); // 最后一项
 }
 // 使用miller_rabin检测是否是素数
 const int kCheckCnt = 8;
 // 为了随机数
 random_device rd;
 mt19937_64 gen(rd());
 bool miller_rabin(ll n) {
     if (n == 2) return true;
     if ((n <= 2) || (n&1^1)) return false;
     // 2^q×m表示原本输入的n-1
     ll m = n, q = 0;
     do { m >>= 1; ++q; } while(m&1^1);
     // 随机数生成,[1,n-1] 均匀分布
     uniform_int_distribution<> dis(1, n-1);
     mod_sys mod;
     mod.set_mod(n);
     for (int i = 0; i < kCheckCnt; ++i)
         if (!miller_rabin(dis(gen), n, q, m, mod))
             return false;
     return true;
 }
模板题推荐hdu2138
Miller-Rabin素数检测算法 acm模板的更多相关文章
- Miller Rabin素数检测与Pollard Rho算法
		一些前置知识可以看一下我的联赛前数学知识 如何判断一个数是否为质数 方法一:试除法 扫描\(2\sim \sqrt{n}\)之间的所有整数,依次检查它们能否整除\(n\),若都不能整除,则\(n\)是 ... 
- Miller Rabin素数检测
		#include<iostream> #include<cstdio> #include<queue> #include<cstring> #inclu ... 
- POJ1811_Prime Test【Miller Rabin素数测试】【Pollar Rho整数分解】
		Prime Test Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 29193 Accepted: 7392 Case Time ... 
- POJ2429_GCD & LCM Inverse【Miller Rabin素数測试】【Pollar Rho整数分解】
		GCD & LCM Inverse Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9756Accepted: 1819 ... 
- POJ1811_Prime Test【Miller Rabin素数測试】【Pollar Rho整数分解】
		Prime Test Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 29193 Accepted: 7392 Case Time ... 
- HDU1164_Eddy'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 ... 
- Miller-Rabin素数检测算法
		遇到了一个题: Description: Goldbach's conjecture is one of the oldest and best-known unsolved problems in ... 
- 关于素数:求不超过n的素数,素数的判定(Miller Rabin 测试)
		关于素数的基本介绍请参考百度百科here和维基百科here的介绍 首先介绍几条关于素数的基本定理: 定理1:如果n不是素数,则n至少有一个( 1, sqrt(n) ]范围内的的因子 定理2:如果n不是 ... 
- 【数论基础】素数判定和Miller Rabin算法
		判断正整数p是否是素数 方法一 朴素的判定 
随机推荐
- HDU2066dijkstra模板题
			问题描述: 题目描述:Problem Description 虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王 ... 
- HDU_3183_RMQ
			http://acm.hdu.edu.cn/submit.php?pid=3183 初探rmq,这道题看了题解还是写了好久.原因是rmq处理字符串时没有自己写min函数,导致把返回的字符当成下标处理了 ... 
- ARTS  Week 12
			Jan 13, 2020 ~ Jan 19, 2020 Algorithm Problem 112. Path Sum (路径总和) 题目链接 题目描述:给定一棵二叉树和一个值 sum ,检查二叉树是 ... 
- bootstrap  按钮组件
			按钮组件主要的类名: .btn-toolbar 把几个 .btn-group 组合在一起,更复杂的组件 .btn-group .btn-group-vertical 垂直堆叠显示 ... 
- Go语言实现:【剑指offer】二维数组中的查找
			该题目来源于牛客网<剑指offer>专题. 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一 ... 
- Nginx总结(八)Nginx服务器的日志管理及配置
			前面讲了如何配置Nginx虚拟主机,大家可以去这里看看nginx系列文章:https://www.cnblogs.com/zhangweizhong/category/1529997.html 今天要 ... 
- 详解SkipList跳跃链表【含代码】
			本文始发于个人公众号:TechFlow,原创不易,求个关注 今天继续介绍分布式系统当中常用的数据结构,今天要介绍的数据结构非常了不起,和之前介绍的布隆过滤器一样,是一个功能强大原理简单的数据结构.并且 ... 
- html  input元素的所有type属性
			<input /> 属性 type="text" 输入框的类型为文本 type="password" 输入框的类型为密码 type="ra ... 
- java 获取两个时间之前所有的日期
			正序(2017-01-01 ~2019-xxxxx) package com.founder.util; import java.text.SimpleDateFormat; import java. ... 
- Hibernate入门之命名策略(naming strategy)详解
			前言 JPA和Hibernate都提供了默认映射策略,通过映射将每个实体类映射到具有相同名称的数据库表,它的每个属性都映射到具有相同属性的列, 但是,在实际项目开发中可能出现与默认命名约定不匹配,也就 ... 
