我们首先看这样一个很简单的问题:判定正整数\(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;
}

转载于:https://www.cnblogs.com/encodetalker/p/9976285.html

miller——rabin判断素数相关推荐

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

    (Miller Rabin算法)判断一个数是否为素数 1.约定 x%y为x取模y,即x除以y所得的余数,当x<y时,x%y=x,所有取模的运算对象都为整数. x^y表示x的y次方.乘方运算的优先 ...

  2. 素数判定算法 MILLER RABIN

    入门级筛素数--试除法,复杂度O(n^2) bool rmprime( long long n ) {for(long long i = 2; i <= sqrt(n) ; i++) if(n% ...

  3. Magic的Miller Rabin素数测定和Pollard's Rho质因子分解法

    boshi大佬帮助了litble,使愚蠢的litble(可能?)学会了这种神奇的算法. orz boshi. 例题:poj1811 Miller Rabin 又称米勒挝饼, 一种神奇的快速判定一个数是 ...

  4. 素数判定质因数分解(数论)(Miller Rabin)(Pollard Rho)

    太玄学了! 我真的被概率的魅力折服了.此前我认为1便是1,0.9999999999-便是0.9999999999-. 但实际上它们有着千丝万缕的关系. 试想,如果一件事发生的概率是0.99999999 ...

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

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

  6. 费尔马小定理素数java_利用费马小定理判断素数

    今天听了ljss神犇的数论课,顿时感觉----我真的是太弱啦! 我只能稍微写一下我能听懂的部分orz 那么这就是今天我为数不多能听懂一点的之一......QAQ 首先先介绍今天的主角:费马小定理 -- ...

  7. ACMNO.23 C语言-素数判定 写一个判断素数的函数,在主函数输入一个整数,输出是否是素数的消息。 输入 一个数 输出 如果是素数输出prime 如果不是输出not prime

    题目描述 写一个判断素数的函数,在主函数输入一个整数,输出是否是素数的消息. 输入 一个数 输出 如果是素数输出prime 如果不是输出not prime 样例输入 97 样例输出 prime 来源/ ...

  8. java 语言如何判断素数_C语言实验之判断素数(循环结构java)方法讲解

    C语言实验之判断素数(循环结构java)方法讲解 Problem Description 从键盘上输入任意一个正整数,然后判断该数是否为素数. 如果是素数则输出"This is a prim ...

  9. erlang(20)-控制抽象与判断素数

    定义自己的for 产生序列 -module(learnerl). -export([get_result/2]).for(Max,Max,F)->[F(Max)]; for(I,Max,F)-& ...

最新文章

  1. storm能不能测试wadl_情感测试:4朵玫瑰花,哪个会最扎手?测你婚后能不能享住TA?...
  2. [Swift]LeetCode496. 下一个更大元素 I | Next Greater Element I
  3. 使用Pandas进行变量衍生
  4. python模拟用户压力测试_Python 工具 Locust 进行负载测试
  5. Codeforces Round #506 (Div. 3) - F. Multicolored Markers (思维)
  6. 分享一个不错的表格样式
  7. 云生态战略首次曝光,牵手精诚中国和神州光大共建云生态
  8. 通过Python扫描代码关键字并进行预警
  9. python文件的分类
  10. Go 将在下个版本支持新型排序算法:pdqsort
  11. ios获取新数据要不要关_iPhone用户注意!不要再滑动关后台,否则……
  12. Java项目:SSM网上超市购物商城管理系统
  13. java 排班日历,排班日历
  14. 【软件安装使用】pano2vr教程
  15. 湘潭大学计算机分数线,湘潭大学录取分数线2021是多少分(附历年录取分数线)
  16. 华为2020秋招笔试试题
  17. c语言计次循环首,易语言内存读取获得当前PC已经登陆微信号的代码
  18. 加速中小企业信息化,SaaS是砖还是宝?
  19. IDEA设置输入忽略大小写
  20. 【Python 实战基础】如何绘制树状图展示Python数据分析师的知识结构

热门文章

  1. Kafka Partition重分配流程简析
  2. 使用Wireguard进行异地组网
  3. Android Studio 开发--近场通信技术
  4. 解决办法:WinSCP 普通用户上传文件没有权限解决
  5. html dom阮一峰,Web Components
  6. python矩阵、解方程、绘图操作
  7. 通达oa考勤可以代打吗_考勤管理
  8. hdu1004——Let the Balloon Rise
  9. GOTS认证辅导,TC是有机产品买卖双方真实交易的证明
  10. 参数辨识最小二乘法——永磁同步电机矢量控制课题拓展