梅森素数 判定总结 - Lucas-Lehmer算法 & Miller-rabin算法
梅森素数
定义:
- if m是一个正整数 and 2^m-1是一个素数 then m是素数
- if m是一个正整数 and m是一个素数 then M(m)=2^m-1被称为第m个梅森数
- if p是一个素数 and M(p)是一个素数 then M(p)被称为梅森素数
Lucas-Lehmer判定法:判定一个梅森数是否是梅森素数
设p是素数,第p个梅森数为M(p)为2^p-1,r1 = 4,对于k >= 2
r(k) = r(k+1)^2-2(modM(p)), 0 <= r(k) <= M(p)
可以得到r(k)序列,则有M(p)是素数,当且仅当r(p-1) = 0(mod M(p))
推论:设p是素数,M(p)为第p个梅森数,则算法复杂度为O(n^3)
梅森素数 - nefu 120
思路:R.1 = 4;R.k = (R.k-1 ^ 2 - 2) % Mp;
如果R.p-1 == 0,则是梅森素数,否则不是。
特殊判断:p == 2,即Mp = 3是梅森素数。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
typedef long long ll;
ll multi(ll a, ll b, ll m)
{
ll ret = 0;
while(b>0)
{
if(b&1)
{
ret = (ret+a)%m;
}
b >>= 1;
a = (a<<1)%m;
}
return ret;
}
int main()
{
ll sum = 1, data[66], tmp;
int n, p;
data[1] = 4;
cin >> n;
while(n--)
{
sum = 1;
cin >> p;
sum <<= p;
sum -= 1;
for(int i = 2; i <= p-1; i++)
{
tmp = multi(data[i-1],data[i-1],sum);
data[i] = (tmp-2)%sum;
}
if(p == 2)
cout << "yes" << endl;
else
{
if(data[p-1] == 0)
cout << "yes" <<endl;
else
cout << "no" << endl;
}
}
return 0;
}
模板:
long long multi(long long a, long long b, long long m){//实现a * b % m的操作,用2 * 3 = 6模拟一下就懂了
long long ans = 0;
while(b > 0){
if(b & 1) ans = (ans+a) % m;
b >>= 1;
a = (a<<1) % m;
}
return ans;
}
//判断是否是梅森素数
bool is_msPrime(int p){
long long r[70];
long long m = 1;
m <<= p; m -=1;//求出Mp;
r[1] = 4LL;
if(p == 2) return true;
for(int i = 2; i <= p-1; ++i)
r[i] = (multi(r[i-1],r[i-1],m)-2) % m;
if(r[p-1] == 0) return true;
return false;
}
Miller-rabin 素数测试:直接判断M(p)是不是素数
理论知识:
费马小定理: 对于素数p和任意整数a,有ap ≡ a(mod p)(同余)。反过来,满足ap ≡ a(mod p),p也几乎一定是素数。
伪素数: 如果n是一个正整数,如果存在和n互素的正整数a满足 an-1 ≡ 1(mod n),我们说n是基于a的伪素数。如果一个数是伪素数,那么它几乎肯定是素数。
Miller-Rabin测试: 不断选取不超过n-1的基b(s次),计算是否每次都有bn-1 ≡ 1(mod n),若每次都成立则n是素数,否则为合数。
还有一个定理,能提高Miller测试的效率:
二次探测定理: 如果p是奇素数,则 x2 ≡ 1(mod p)的解为 x = 1 || x = p - 1(mod p);
两个高效求解a*b%m a^b%m的方法
// a * b % n
//例如: b = 1011101那么a * b mod n = (a * 1000000 mod n + a * 10000 mod n + a * 1000 mod n + a * 100 mod n + a * 1 mod n) mod n
ll mod_mul(ll a, ll b, ll n) {
ll res = 0;
while(b) {
if(b&1) res = (res + a) % n;
a = (a + a) % n;
b >>= 1;
}
return res;
}
//a^b % n
//同理
ll mod_exp(ll a, ll b, ll n) {
ll res = 1;
while(b) {
if(b&1) res = mod_mul(res, a, n);
a = mod_mul(a, a, n);
b >>= 1;
}
return res;
}
代码如下:
bool miller_rabin(ll n) {
if(n == 2 || n == 3 || n == 5 || n == 7 || n == 11) return true;
if(n == 1 || !(n%2) || !(n%3) || !(n%5) || !(n%7) || !(n%11)) return false;
ll x, pre, u;
int i, j, k = 0;
u = n - 1; //要求x^u % n
while(!(u&1)) { //如果u为偶数则u右移,用k记录移位数
k++; u >>= 1;
}
srand((ll)time(0));
for(i = 0; i < S; ++i) { //进行S次测试
x = rand()%(n-2) + 2; //在[2, n)中取随机数
if((x%n) == 0) continue;
x = mod_exp(x, u, n); //先计算(x^u) % n,
pre = x;
for(j = 0; j < k; ++j) { //把移位减掉的量补上,并在这地方加上二次探测
x = mod_mul(x, x, n);
if(x == 1 && pre != 1 && pre != n-1) return false; //二次探测定理,这里如果x = 1则pre 必须等于 1,或则 n-1否则可以判断不是素数
pre = x;
}
if(x != 1) return false; //费马小定理
}
return true;
}
梅森素数 判定总结 - Lucas-Lehmer算法 & Miller-rabin算法的更多相关文章
- Pollard rho算法+Miller Rabin算法 BZOJ 3668 Rabin-Miller算法
BZOJ 3667: Rabin-Miller算法 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 1044 Solved: 322[Submit][ ...
- 【数论基础】素数判定和Miller Rabin算法
判断正整数p是否是素数 方法一 朴素的判定
- Miller Rabin算法详解
何为Miller Rabin算法 首先看一下度娘的解释(如果你懒得读直接跳过就可以反正也没啥乱用:joy:) Miller-Rabin算法是目前主流的基于概率的素数测试算法,在构建密码安全体系中占有重 ...
- Miller Rabin 算法简介
0.1 一些闲话 最近一次更新是在2019年11月12日.之前的文章有很多问题:当我把我的代码交到LOJ上,发现只有60多分.我调了一个晚上,尝试用{2, 3, 5, 7, 11, 13, 17, 1 ...
- Miller Rabin算法学习笔记
定义: Miller Rabin算法是一个随机化素数测试算法,作用是判断一个数是否是素数,且只要你脸不黑以及常数不要巨大一般来讲都比\(O(\sqrt n)\)的朴素做法更快. 定理: Miller ...
- (Miller Rabin算法)判断一个数是否为素数
1.约定 x%y为x取模y,即x除以y所得的余数,当x<y时,x%y=x,所有取模的运算对象都为整数. x^y表示x的y次方.乘方运算的优先级高于乘除和取模,加减的优先级最低. 见到x^y/z这 ...
- Miller-Rabin算法 codevs 1702 素数判定 2
转载自:http://www.dxmtb.com/blog/miller-rabbin/ 普通的素数测试我们有O(√ n)的试除算法.事实上,我们有O(slog³n)的算法. 定理一:假如p是质数,且 ...
- Miller Rabin素数检测与Pollard Rho算法
一些前置知识可以看一下我的联赛前数学知识 如何判断一个数是否为质数 方法一:试除法 扫描\(2\sim \sqrt{n}\)之间的所有整数,依次检查它们能否整除\(n\),若都不能整除,则\(n\)是 ...
- poj 1811 Pallor Rho +Miller Rabin
/* 题目:给出一个数 如果是prime 输出prime 否则输出他的最小质因子 Miller Rabin +Poller Rho 大素数判定+大数找质因子 后面这个算法嘛 基于Birthday Pa ...
随机推荐
- ledecode Reverse Words in a String III
557. Reverse Words in a String III Given a string, you need to reverse the order of characters in ea ...
- Theme Section---hdu4763(kmp, Next数组的运用)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4763 题意就是求s串中满足EAEBE格式的E的最大长度:我们可以枚举前缀和后缀的所有匹配(k)看是否在 ...
- Golang&Python测试thrift
接上篇,安装好之后,就开始编写IDL生成然后测试. 一.生成运行 参考 http://www.aboutyun.com/thread-8916-1-1.html 来个添加,查询. namespace ...
- MapReduce学习笔记
一.MapReduce概述 MapReduce 是 Hadoop 的核心组成, 是专用于进行数据计算的,是一种分布式计算模型.由Google提出,主要用于搜索领域,解决海量数据的计算问题. MapRe ...
- Java编程:将具有父子关系的数据库表数据转换为树形结构,支持无限层级
在平时的开发工作中,经常遇到这样一个场景,在数据库中存储了具有父子关系的数据,需要将这些数据以树形结构的形式在界面上进行展示.本文的目的是提供了一个通用的编程模型,解决将具有父子关系的数据转换成树形结 ...
- Python-读入json文件并进行解析及json基本操作
import json def resolveJson(path): file = open(path, "rb") fileJson = json.load(file) fi ...
- DIV+CSS如何让文字垂直居中?
在说到这个问题的时候,也许有人会问CSS中不是有vertical-align属性来设置垂直居中的吗?即使是某些浏览器不支持我只需做少许的CSS Hack技术就可以啊!所以在这里我还要啰嗦两句,CSS中 ...
- Flask系列(十一)整合Flask中的目录结构(sqlalchemy-utils)
一.SQLAlchemy-Utils 由于sqlalchemy中没有提供choice方法,所以借助SQLAlchemy-Utils组件提供的choice方法 import datetime from ...
- sdut3138: N!(计算n!中结尾零的个数)
题目:http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=3138 算法思想:在1-10两个数相乘要产 ...
- Linux环境下Netstat与PS的使用
Linux下用netstat查看网络状态.端口状态 在linux一般使用netstat 来查看系统端口使用情况步. netstat命令是一个监控TCP/IP网络的非常有用的工具,它可以显示路由表.实际 ...