Miller Rabbin 算法—费马定理+二次探测+随机数 (讲解+例题:FZU1649 Prime number or not)
0.引入
那年,机房里来了个新教练, 口胡鼻祖lhy
第一节课,带我们体验了暴力的神奇,
第二节课,带我们体验了随机数的玄妙,
……
那节课,便是我第一次接触到Miller Rabbin算法,
直到现在,终于搞懂了一些。
该算法(名字过长,不想打了)主要是解决快速判断一个极大的数是否是质数的问题。
我们知道,能保证正确的最快的算法,就是的复杂度,不能再小了,对于一个很大的long long,复杂度达到O(1e9)
但是该算法却能在的时间复杂度内判断,(如果用了光速乘,还可以变为
)
那究竟是为什么呢?
我们先特判了小质数后,再进入下面的算法
1.费马定理
我们知道,对于一个质数p,和比它小的数a,有
所以我们可以先判断 p 是否符合费马定理,不符合就肯定不是质数。
但是符合也不一定是质数,先不说随便在小于一个合数 p 的数中选一些数可能恰好都符合费马定理,就算把1~p-1都穷举完了,也有合数是可以满足上面的式子的,那就是卡迈克尔数。
但是这一步判断至少确定了枚举到的 a 是有逆元的吧……
2.二次探测
若有
其中 p 是质数,y < p,则
这就是二次探测的原理
然后大家知道,这篇文章不是在证定理,而是在讲算法,所以注重算法过程而不是算法推导,所以笔者就直接讲过程了!
由于上面费马定理已经判断了
而若p是质数,p-1就一定是偶数了(2已经特判掉了)可以分解出很多2出来,
设
那么先算出 ,然后每次
把它平方,只要第一次碰到 a==1 的情况,就看前一次的 a 是多少,如果不是p-1那么该数就是合数,否则就继续算法过程,总会碰到 a==1 的情况,因为最后会乘到
。
3.随机数
随便选一个数 a 来做二次探测,让合数躲过的几率只有10%左右,
那么随机选10个、20个、30个数做二次探测,让合数躲过的几率就小得多了,可以小到同出现相同指纹的概率这么小,(但前提是足够随机)
所以我们就放心做十次二次探测,每次选一个1~p-1中的随机 a 跑上面的过程,把这个10算作一个log的话,复杂度也只有了。
4.例题
FZU1649 质数还是合数
一道该算法的板题
CODE
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<algorithm>
#define MAXN 65545
#define MAXM 35
#define ENDL putchar('\n')
#define LL long long
#define DB double
#define lowbit(x) ((-x)&(x))
//#define int LL
using namespace std;
inline LL read() {
LL f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s == '-')f = -1;s = getchar();}
while(s >= '0' && s <= '9') {x = x * 10 + (s - '0');s = getchar();}
return x * f;
}
const LL jzm = 1000000007;
int n,m,i,j,s,o,k;
LL safemul(LL a,LL b,LL zxy) {
LL res = 0;if(a < b) swap(a,b);
while(b>0) {
if(b & 1ll) (res += a) %= zxy;
(a <<= 1ll) %= zxy;
b >>= 1;
}
return res;
}
LL qkpow(LL a,LL b,LL zxy) {
LL res = 1;
while(b>0) {
if(b & 1ll) res = safemul(res,a,zxy);
a = safemul(a,a,zxy);
b >>= 1;
}
return res % zxy;
}
LL Rand() {return rand()*rand()+rand();}
bool Miller_rabbin(LL p) {
if(p == 2 || p == 3 || p == 5) return 1;
if(p <= 1) return 0;
LL nm = p-1;
nm /= lowbit(nm);
for(int id = 1;id <= 10;id ++) {
LL a = Rand() % p;
if(qkpow(a,p-1,p) != 1ll) return 0;
a = qkpow(a,nm,p);
LL pre = p-1;
while(a != 1) {
pre = a;
a = safemul(a,a,p);
}
if(pre != p-1) return 0;
}
return 1;
}
int main() {
srand(time(0));
LL N;
while(scanf("%lld",&N) == 1) {
printf(Miller_rabbin(N) ? "It is a prime number.\n":"It is not a prime number.\n");
}
return 0;
}
Miller Rabbin 算法—费马定理+二次探测+随机数 (讲解+例题:FZU1649 Prime number or not)的更多相关文章
- 【数论基础】素数判定和Miller Rabin算法
判断正整数p是否是素数 方法一 朴素的判定
- Miller Rabin算法详解
何为Miller Rabin算法 首先看一下度娘的解释(如果你懒得读直接跳过就可以反正也没啥乱用:joy:) Miller-Rabin算法是目前主流的基于概率的素数测试算法,在构建密码安全体系中占有重 ...
- Miller-Robin与二次探测
素数在数论中经常被用到.也是数论的基础之一. 人们一直在讨论的问题是,怎样快速找到素数?或者判断一个数是素数? 1.根号n枚举 原始暴力方法. 2.埃氏筛 每个合数会被筛质因子次数次.复杂度O(Nlo ...
- 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 ...
- 算法(二)之遗传算法(SGA)
算法(二)之遗传算法(SGA) 遗传算法(Genetic Algorithm)又叫基因进化算法或进化算法,是模拟达尔文的遗传选择和自然淘汰的生物进化过程的计算模型,属于启发式搜索算法一种. 下面通过下 ...
- (Miller Rabin算法)判断一个数是否为素数
1.约定 x%y为x取模y,即x除以y所得的余数,当x<y时,x%y=x,所有取模的运算对象都为整数. x^y表示x的y次方.乘方运算的优先级高于乘除和取模,加减的优先级最低. 见到x^y/z这 ...
- java 解决Hash(散列)冲突的四种方法--开放定址法(线性探测,二次探测,伪随机探测)、链地址法、再哈希、建立公共溢出区
java 解决Hash(散列)冲突的四种方法--开放定址法(线性探测,二次探测,伪随机探测).链地址法.再哈希.建立公共溢出区 标签: hashmaphashmap冲突解决冲突的方法冲突 2016-0 ...
- 70 数组的Kmin算法和二叉搜索树的Kmin算法对比
[本文链接] http://www.cnblogs.com/hellogiser/p/kmin-of-array-vs-kmin-of-bst.html [分析] 数组的Kmin算法和二叉搜索树的Km ...
随机推荐
- 构建基于React18的电子表格程序
背景 2022年3月29日,React正式发布18.0.0.本次升级内容包括开箱即用的改进,如自动批处理.新的API(如startTransition)和支持Suspense 的流式服务器端渲染.关于 ...
- 【Azure 应用服务】NodeJS Express + MSAL 实现API应用Token认证(AAD OAuth2 idToken)的认证实验 -- passport.authenticate('oauth-bearer', {session: false})
问题描述 在前两篇博文中,对NodeJS Express应用 使用MSAL + AAD实现用户登录并获取用户信息,获取Authorization信息 ( ID Token, Access Token) ...
- 记录bug的贴子
这个贴子用来记录一些,平时关注新闻,暴露出来的bug,引以为戒. 2019/01/21 - 拼多多出现大量100元无门槛券 关键词: 风险控制:羊毛党: https://www.zhihu.com/q ...
- redis相关知识点
redis 的相关知识点 启动 启动代码 redis-cli -a 密码 通用命令 expire: 设置有效期 expire name 10 key key * 相关数据类型 String set:添 ...
- 告别单调,Django后台主页改造 - 使用AdminLTE组件
前言 之前我做了个Django的项目,为了让管理后台更加美观,我对Django(应该说是SimpleUI的)默认的Admin后台主页进行改造,具体可以看这篇文章:项目完成 - 基于Django3.x版 ...
- 抓包整理外篇fiddler————了解工具栏[一]
前言 抓包本篇还没写完,因为在工作中,发现有人用fiddler 用的还不是很好,所以去介绍一下这个东西,fiddler大体分为10多个章节. 正文 首先了解一下fiddler的抓包原理哈. 可以看到当 ...
- 执行docker一系列命令失败
出现这种情况之后,执行下面的命令即可. systemctl restart docker
- 研发效能|Kubernetes核心技术剖析和DevOps落地经验
本文主要介绍Kubernetes 的核心组件.架构.服务编排,以及在集群规模.网络&隔离.SideCar.高可用上的一些使用建议,尤其是在CICD中落地,什么是 GitOps. 通过此文可彻底 ...
- 从工程师到技术leader思维升级
身处职场之中,太多话题相围绕,"个人成长"."管理"或许是讨论的最多的了. 但"个人成长"和"管理"却是大不相同的两件事 ...
- 2022-07-21 第四组 java之继承
目录 一.继承 1.概念 2.语法 3.父类成员访问 3.1 子类访问父类的成员变量 3.1.1 子类和父类中不存在同名的成员变量 3.1.2 子类和父类中不存在同名的成员变量 3.2 子类中访问父类 ...