我是靠谱客的博主 大意发夹,最近开发中收集的这篇文章主要介绍星星之火OIer:素数判断——Miller_Rabin——普通判断——Miller Rabin素数测试法,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

在这一讲中,我们来看一下如何判断一个素数

常用的有2

目录

——普通判断

——Miller Rabin素数测试法

算法前置::

算法流程::

代码::


o(sqrt{n})=o(n^frac{1}{2})——普通判断

2sqrt{n}依次判断n % i是否等于0

代码如下::

for(int i=2;i<=int(sqrt(n));i++)
if(n%i==0) {
puts("Unprime");//将就看到起,我也不晓得怎么说了
return 0;
}
puts("Prime");

这是很简单的

o(sqrt{sqrt{n}})=o(n^frac{1}{4})——Miller Rabin素数测试法

这是一个可以检测rp的算法

因为这是基于随机算法而来的素数测试法

算法前置::

  • 费马小定理:若a是整数,p是质数,且a%p!=0,则a^{p-1}equiv 1(mod p),但反过来不一定成立,即如果a^{p-1}equiv 1(mod p)a,p互质不能退出p为质数,但这种数是极少见的
  • 二次探测定理:若p是质数,且0<x<p,则方程x^2-1equiv 1(mod p)的解为x=1x=p-1
  • 模运算:(a*b)%n=(a%n*b%n)%n
  • 快速幂、快速积:运用二分的思想,快速求出a^ba*b

算法流程::

  • 判断n是不是2,如果是,返回true
  • 判断n是否小于2或者n%2==0,如果是,返回false
  • n-1=u*2^t并求出u,t,其中u是奇数
  • x=(a^u)%n
  • 然后是t次循环,每次循环都让y=(x^2)%n,x=y,这样t次循环之后x=a^{u*2^t}=a^{n-1}
  • 因为根据二次探测定理定理,如果x!=1||x!=n,那么n肯定不是质数,返回false
  • 然后又可以用费马小定理,若x!=1,则n也不是质数
  • 然鹅因为Miller_Rabin算法的正确率只有75%左右,所以要循环k次,k请自取,算法错误率为frac{1}{4^k}
  • 然后就看rp

更多详细的解释请看代码,谢谢

代码::

#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define il inline
#define rt return
#define bl bool
#define vd void
il vd read(ll &x) {
x=0;
ll f=1;
char s=getchar();
while(s<'0'||s>'9') {
if(s=='-')
f=-1;
s=getchar();
}
while(s>='0'&&s<='9') {
x=x*10+s-48;
s=getchar();
}
x*=f;
}
il vd pr(ll x) {
if(x<0) {
putchar('-');
x=-x;
}
if(x>9)
pr(x/10);
putchar(x%10+48);
}//快读快输不解释
il ll ksc(ll a,ll b,ll n) {//快速幂和快速积请看作者的另一篇博客
ll ans=0;
while(b) {
if(b&1)
ans=(ans+a)%n;
a=(a<<1)%n;
b>>=1;
}
rt ans;
}
il ll ksm(ll a,ll b,ll n) {
ll ans=1;
while(b) {
if(b&1)
ans=ksc(ans,a,n);
a=ksc(a,a,n);
b>>=1;
}
rt ans;
}
il bl miller_rabin(ll n) {//Miller_Rabin算法
ll a,b,x,y,u,t;
if(n==2)//看n是否为2
rt 1;//为2就是质数
else if(n<2||!(n&1))//小于2或是2的倍数
rt 0;//不是质数
for(t=0,u=n-1;!(u&1);t++,u>>=1);//求出u和t
for(ll i=0;i<20;i++) {//这个20是可以想开多大就开多大的/*只要不超时*/
a=rand()%(n-2)+2;//随机生成一个数
x=ksm(a,u,n);//快速幂
for(ll j=0;j<t;j++) {
y=ksc(x,x,n);//快速积
if(y==1&&x!=1&&x!=n-1)//二次探测定理
rt 0;//不是质数
x=y;//更新
}
if(x!=1)//费马小定理
rt 0;//不是质数
}
rt 1;//有很大可能是质数
}
ll t,n,a;
int main() {
srand((unsigned)time(NULL));
read(t);
while(t--) {
read(n);
if(miller_rabin(n))
puts("YES");
else
puts("NO");
}
}

大概就是这样了,有错误请指出,谢谢大家啦

最后

以上就是大意发夹为你收集整理的星星之火OIer:素数判断——Miller_Rabin——普通判断——Miller Rabin素数测试法的全部内容,希望文章能够帮你解决星星之火OIer:素数判断——Miller_Rabin——普通判断——Miller Rabin素数测试法所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(73)

评论列表共有 0 条评论

立即
投稿
返回
顶部