miller——rabin判断素数
我们首先看这样一个很简单的问题:判定正整数\(n\)是否为素数
最简单的做法就是枚举\(2\)到\(n\)的所有数,看是否有数是\(n\)的因数,时间复杂度\(O(n)\)
稍微优化一下发现只要枚举\(2\)到\(\sqrt{n}\)中的数就可以了
然后发现数据范围\(n\leq 10^{18}\),时间复杂度直接就死掉了QAQ
我们就要考虑新的方法了
首先引入两个定理
1、费马小定理
如果\(p\)是素数,且\(gcd(a,b)=1\),那么\(a^{p-1}\equiv 1(mod \ n)\)
证明什么的你随便找本数论书自己翻一下
注意它的逆定理不一定成立(或者说是它的逆定理在大多数情况下都成立)
2、二次探测定理(其实这也没有一个准确的名字)
如果\(p\)是奇素数,\(x<p\),且\(x^2\equiv1(mod\ p)\),那么\(x=1\)或\(xp=-1\)
证明:由同余式知\(x^2-1\equiv0(mod\ p)\),即\(p|(x+1)(x-1)\)
又由\(p\)是素数知\(p|x-1\)或\(p|x+1\),解得\(x=1\)或\(x=p-1\)
诶等等zzr没事给证明干嘛?zzr不是最讨厌证明了吗
由上面很简单的证明过程我们可以发现,\(x=1\)和\(x=p-1\)这两个解其实是对所有的\(p\)都成立的
即无论\(p\)取什么值\(x\)取上面两个值是一定可以的
但是当\(p\)是一个合数的时候,此时原同余方程的解\(x\)就不只上面这两个了,而是会有多个
换一句话说:如果上面的\(x\)取到了1和\(p-1\)以外的数,就说明\(p\)不是一个素数了
我们主要利用上面两个性质来进行素数判定
1、取\(2^q*m=n-1\)(\(q,m\)均为正整数且\(m\)为奇数),同时任意取小于\(n\)的正整数\(a\)
2、求出\(a^{n-1}\text%n\),如果这个值不为1那么\(n\)一定是合数(利用费马小定理)
3、遍历\(i\),使得\(1\leq i \leq q\),如果\(2^i*m\text%n=1\)并且\(a^{i-1}*m\text%n!=1或n-1\),那么由二次探测定理就知道原同余方程出现一个特殊解,说明\(n\)不是一个素数
上面的方法有一个小问题:由于费马小定理的逆定理不一定成立(在大多数情况下成立),因此有时我们会对\(n\)进行误判,具体的,每做一次发生误判的概率是\(\frac{1}{4}\)
解决的方法在上面的解法中也有体现:换用不同的\(a\),多进行几次即可
好了上面就是完整的miller-rabin测试了
一道例题:poj3518Prime Gap
题意:两个相邻的素数的差值叫做Prime Gap。输入一个K,求K两端的素数之差,如果K本身是一个素数,输出0;
分析:其实数据很小你直接筛一下也可以
或者你直接暴力寻找当前这个数相邻的数是否是质数,两端分别记录第一次找到的质数即可
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;
#define int long long
int n;
int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
int mul(int x,int y,int n)
{
x%=n;y%=n;
int ans=0,sum=x;
while (y)
{
int tmp=y%2;y/=2;
if (tmp) ans=(ans+sum)%n;
sum=(sum+sum)%n;
}
return ans;
}
int qpow(int x,int y,int n)
{
int ans=1,sum=x;
while (y)
{
int tmp=y%2;y/=2;
if (tmp) ans=mul(ans,sum,n);
sum=mul(sum,sum,n);
}
return ans;
}
bool prime(int m,int q,int a,int n)
{
int now=qpow(a,m,n);
if ((now==1) || (now==n-1)) return 1;
int i;
for (i=1;i<=q;i++)
{
int x=mul(now,now,n);
if ((x==1) && (now!=1) && (now!=n-1)) return 0;
now=x;
}
if (now!=1) return 0;//其实这里是将费马小定理的检测放在了最后,省去再做一次快速幂
return 1;
}
bool miller_rabin(int x)
{
if (x==2) return 1;
if ((x<2) || (x%2==0)) return 0;
int num=x-1,tim=0;
while ((num) && (num%2==0)) {num/=2;tim++;}
//cout << num << " " <<tim << endl;
int i;
for (i=1;i<=10;i++)//一般都会进行20次左右,不过数据范围小对吧2333
{
int a=rand()%(x-1)+1;
if (!prime(num,tim,a,x)) return 0;
}
return 1;
}
void work()
{
if (miller_rabin(n)) {printf("0\n");return;}
//cout <<1;
int l=n-1,r=n+1;
while (!miller_rabin(l)) l--;
while (!miller_rabin(r)) r++;
printf("%d\n",r-l);
}
signed main()
{
n=read();
while (n)
{
work();
n=read();
}
return 0;
}
miller——rabin判断素数的更多相关文章
- Miller Rabin 大素数测试
PS:本人第一次写随笔,写的不好请见谅. 接触MillerRabin算法大概是一年前,看到这个算法首先得为它的神奇之处大为赞叹,竟然可以通过几次随机数据的猜测就能判断出这数是否是素数,虽然说是有误差率 ...
- 与数论的厮守01:素数的测试——Miller Rabin
看一个数是否为质数,我们通常会用那个O(√N)的算法来做,那个算法叫试除法.然而当这个数非常大的时候,这个高增长率的时间复杂度就不够这个数跑了. 为了解决这个问题,我们先来看看费马小定理:若n为素数, ...
- 关于素数:求不超过n的素数,素数的判定(Miller Rabin 测试)
关于素数的基本介绍请参考百度百科here和维基百科here的介绍 首先介绍几条关于素数的基本定理: 定理1:如果n不是素数,则n至少有一个( 1, sqrt(n) ]范围内的的因子 定理2:如果n不是 ...
- 【数论基础】素数判定和Miller Rabin算法
判断正整数p是否是素数 方法一 朴素的判定
- Miller Rabin素数检测与Pollard Rho算法
一些前置知识可以看一下我的联赛前数学知识 如何判断一个数是否为质数 方法一:试除法 扫描\(2\sim \sqrt{n}\)之间的所有整数,依次检查它们能否整除\(n\),若都不能整除,则\(n\)是 ...
- 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 ...
随机推荐
- from bs4 import BeautifulSoup 报错
一: BeautifulSoup的安装: 下载地址:https://www.crummy.com/software/BeautifulSoup/bs4/download/4.6/ 下载后,解压缩,然后 ...
- centos7 安装phpmyadmin
1.先安装epel,不然安装pgpmyadmin时会出现找不到包. yum install epel-release rpm -ivh http://rpms.famillecollet.com/en ...
- 解决scrapy报错:ModuleNotFoundError: No module named 'win32api'
ModuleNotFoundError: No module named 'win32api' 表示win32api未安装 解决办法: 下载对应python版本的win32api,并安装. 下载地址: ...
- MySQL慢查询日志配置方式 slow_query_log
MySQL慢查询(一) - 开启慢查询 - 鲁玉成 - 博客园 https://www.cnblogs.com/luyucheng/p/6265594.html mysql开启慢查询方法 - lava ...
- Windows和Linux的Jmeter分布式集群压力测试
Windows的Jmeter分布式集群压力测试 原文:https://blog.csdn.net/cyjs1988/article/details/80267475 在使用Jmeter进行性能测试时, ...
- Laravel 5.2+ 使用url()全局函数返回前一个页面的地址
注意:文章标题中5.2+表示该文章内容可向上兼容,适用于Laravel版本5.2及更高(目前最新为5.6),但不可向下兼容,即不适用于5.2版本以下.推荐大家花一点点时间,将自己的Laravel更新至 ...
- embed标签的flash层级太高问题
因为客户要求,项目得兼容IE的兼容模式 页面到了flash都会遮挡底部悬浮的导航. 改变浮动窗口和embed的层级还是不可以.应该不是层级的关系. 最后百度解决方案:在embed标签内添加了wmode ...
- RedHat 安装RabbitMQ
(以下均以root用户执行) 1.安装配置epel源rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noar ...
- commons-lang
今天在编码的过程中,对于null,采用==null进行判断.并且为了过滤"",使用了str.trim().length()==0,当str为null时,报空指针异常. 于是决定使用 ...
- Mybatis-java.lang.RuntimeException: org.apache.ibatis.exceptions.PersistenceException: ### Error building SqlSession. ### The error may exist in sqlmap/User.xml ### Cause: org.apache.ibatis.builder.B
mappers(映射器) 使用相对于类路径的资源 如:<mapper resource="sqlmap/User.xml" /> 使用完全限定路径 如:<mapp ...