您的位置:首页 > 其它

Miller-Rabin素数测试

2015-07-03 15:54 387 查看
如果要判断一个比较大的数是否为素数,那么此时传统的试除法和筛法显然不再适用,我们引入一种概率型素数判定方法——Miller-Rabin素数测试。

由费马小定理可以知道,若n是素数且a是整数,则满足a^n≡a(mod n).若存在a不满足上式,那么n是合数。由此我们定义伪素数:令a是一正整数,若n是合数且满足a^n≡a(mod n),那么n称为以a为基的伪素数。

Miller-Rabin素数测试基于费马小定理:假如n是素数且gcd(a,n)=1,那么a^(n-1)≡1(mod n).如果a^(n-1)≡1(mod n)(a为任意小于n的正整数),则可近似认为n为素数,取多个底进行试验,次数越多,n为素数的概率越大。

定义卡迈克尔数:一个合数n,若对于所有满足gcd(b,n)=1的正整数b都有b^(n-1)≡1(mod n)成立,则称之为卡迈克尔数.

为了排除卡迈克尔数导致Miller-Rabin测试出现错误,我们引进二次探测定理:如果p是素数且0<x<p,则方程x^2%p=1的解为x=1或x=p-1.

改进后的Miller-Rabin素数测试实现代码如下:

#include <cstdio>
#include <iostream>
#include <cstdlib>
using namespace std;
#define N 10
typedef long long LL;
LL random(LL n)
{
return (LL)((double)rand()/RAND_MAX*n+0.5);
}
LL multi(LL a,LL b,LL m) //计算a*b%m
{
LL ret=0;
while(b)
{
if(b&1) ret=(ret+a)%m;
b>>=1;
a=(a<<1)%m;
}
return ret;
}
LL quick_mod(LL a,LL b,LL m) //计算a^b%m
{
LL ans=1;
while(b)
{
if(b&1)
{
ans=multi(ans,a,m);
b--;
}
b>>=1;
a=multi(a,a,m);
}
return ans;
}
bool miller_rabin(LL n)
{
if(n==2) return true;
if(n<2||!(n&1)) return false;
LL m=n-1;
int k=0;
while((m&1)==0)
{
k++;
m>>=1;
}
for(int i=0; i<N; i++)
{
LL a=rand()%(n - 1)+1;
LL x=quick_mod(a,m,n);
LL y=0;
for(int j=0;j<k;j++)
{
y=multi(x,x,n);
if(y==1&&x!=1&&x!=n-1) return false;
x=y;
}
if(y!=1) return false;
}
return true;
}
int main()
{
LL n;
while(cin>>n)
if(miller_rabin(n)) puts("yes");
else puts("no");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: