利用费马小定理与概率论的知识,对一个数进行MILLER测试,对于素数n=2^s-1,随机选择一个数a,如果as%n==1,a^(s/2)==-1那么就通过测试,判定为素数。出错的概率小于等于0.25,对这个样本进行多次测试,那么出错的概率就很小了。
书上的代码打下来的,用个转载吧。
#include<time.h>
#include<stdio.h>
#include<iostream>
#define Times 12
using namespace std;
long long random(long long n)
{
return (long long)((double)rand()/RAND_MAX*n+0.5);
}
long long multi(long long a,long long b,long long m)
{
long long ret=0;
while(b>0)
{
if(b&1)
ret=(ret+a)%m;
b>>=1;
a=(a<<1)%m;
}
return ret;
}
long long quick_mod(long long a,long long b,long long m)
{
long long ans=1;
a%=m;
while(b)
{
if(b&1)
{
ans=multi(ans,a,m);
b--;
}
b/=2;
a=multi(a,a,m);
}
return ans;
}
bool Witness(long long a,long long n)
{
long long m=n-1;
int j=0;
while(!(m&1))
{
j++;
m>>=1;
}
long long x=quick_mod(a,m,n);
if(x==1||x==n-1)
return false;
while(j--)
{
x=x*x%n;
if(x==n-1)
return false;
}
return true;
}
bool miller_rabin(long long n)
{
if(n<2)
return false;
if(n==2)
return true;
if(!(n&1))return false;
for(int i=1;i<Times;i++)
{
long long a=random(n-2)+1;
if(Witness(a,n))return false;
}
return true;
}
int main()
{
int ncases,p;
long long n;
scanf("%d",&ncases);
while(ncases--)
{
scanf("%d",&p);
n=((long long)1<<p)-1;
if(miller_rabin(n))
cout<<"yes"<<endl;
else
cout<<"no"<<endl;
}
return 0;
}