http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=120
1.打表
//梅森素数
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
typedef unsigned long long ULL;
const int a[]={2,3,5,7,13,17,19,31,61};
int main()
{
int T;
while(scanf("%d",&T)==1)
{
while(T--)
{
int n;
scanf("%d",&n);
bool flag=false;
for(int i=0;i<9;i++)
if(a[i]==n) flag=true;
if(flag) cout<<"yes"<<endl;
else cout<<"no"<<endl;
}
}
return 0;
}
2.卢卡斯-莱默素数测试
//梅森素数 卢卡斯-莱默判定法
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long LL;
const int maxn=70+5;
LL multi(LL a,LL b,LL k) //a*b%k 避免溢出所以把乘法变成了加法
{
LL ret=0;
while(b)
{
if(b&1) ret=(ret+a)%k;
b>>=1;
a=(a<<1)%k;
}
return ret;
}
int main()
{
int T;
while(scanf("%d",&T)==1)
{
while(T--)
{
int n;
scanf("%d",&n);
LL k=1;
k<<=n;
k--; //得到梅森数
LL data[maxn];
data[1]=4;
for(LL i=2;i<=n-1;i++)
{
LL temp=multi(data[i-1],data[i-1],k);
data[i]=(temp-2)%k;
}
if(n==2||data[n-1]==0) cout<<"yes"<<endl;
else cout<<"no"<<endl;
}
}
return 0;
}
3.miller-rabin素数测试
//Miller素数测试方法
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
using namespace std;
typedef long long LL;
int tim=12; //Miller测试次数
LL k;
LL choose() //选择基底
{
return rand()%(k-2)+1;
}
LL multi(LL a,LL b,LL n) //a*b%n
{
LL ret=0;
while(b)
{
if(b&1) ret=(ret+a)%n;
b>>=1;
a=(a<<1)%n;
}
return ret;
}
LL pow_mod(LL a,LL b,LL MOD) //a^b%n
{
LL res=1;
while(b)
{
if(b&1) res=multi(res,a,MOD);
a=multi(a,a,MOD);
b>>=1;
}
return res;
}
bool witness(LL a,LL n)
{
LL m=n-1;
int j=0;
while(!(m&1))
{
j++;
m>>=1;
}
LL x=pow_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(LL n)
{
if(n<2||n%2==0) return false;
else if(n==2) return true;
//做tim次独立的测试
for(int i=0;i<tim;i++)
{
LL a=choose(); //选择基底
if(witness(a,n)) return false;
}
return true;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
LL n;
srand(time(NULL));
scanf("%lld",&n);
k=1;
k<<=n;
k--;
if(miller_rabin(k)) cout<<"yes"<<endl;
else cout<<"no"<<endl;
}
return 0;
}