Miller-Rabin 素数判定 与 Pollard Rho
今天打模拟赛的时候没想到
参考文献:
这个东西是干嘛的捏。
在一个较为快速的时间内判断一个数是不是质数。
首先我们有两个前置知识。
-
费马小定理:当
为质数时, -
二次探测定理:如果
是奇素数,那么如果有 ,如果解为 ,那么 大概率为质数,否则 一定为合数。
而其实对于素数判定来说,我们还有费马素数判定。
即倘若
而辅助的东西就是
所以我们先要指导一下为什么二次探测定理是正确的。
二次探测定理证明:
也就是说
所以
证毕。
实现:
而对于
而任意偶数一定可以表示成
我们将逐次进行分解枚举,第一次判断
然后我们对于所有的这些都进行判定之后就可以了。
但是这样我们归根结底也只能大概率判断他是一个素数,而不能确定,所以我们需要使用多个底数,然后有一些说法。
一般来说使用
单次判定时间复杂度为
还有一些具体的细节在代码里给出:
点击查看代码
int prime[10+10]={2,3,5,7,11,233,331},tim=7;
LL ksm(LL x,LL y,LL MODD) {
LL ret=1;
while(y) {
if(y&1) ret=ret*x%MODD;
x=x*x%MODD;
y>>=1;
}
return ret;
}
LL mul(LL x,LL y,LL MODD) {
LL ret=0;
while(y) {
if(y&1) ret=(ret+x)%MODD;
x=(x+x)%MODD;
y>>=1;
}
return ret;
}
bool miller_rabin(LL a,LL n) {
LL s=n-1,r=0;
while(!(s&1)) {
s>>=1;
++r;
}
LL x=ksm(a,s,n);//先求出a^u
for(int i=0;i<r;++i) {//每次翻倍
LL tmp=mul(x,x,n);//太大的时候用龟速乘,如果不用的话时间复杂度降到 $O(klogn)$
if(x!=1&&x!=n-1&&tmp==1) return false;
//将上一个x,作为底,如果他的平方为1,且他自己不为1,就不符合二次探测
x=tmp;
}
return (x==1);//费马判定
}
bool check(int n) {
if(n==1) return false;//特判
for(int i=0;i<tim;++i) {
if(n==prime[i]) return true;//特判
if(!miller_rabin(prime[i],n)) {
return false;
}
}
return true;
}
咕咕咕
本文作者:ddl1no2home
本文链接:https://www.cnblogs.com/ddl1no2home/p/17655003.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步