题意:给出p(1<p<=62),让你求Mp=2^p-1是否为梅森素数。
梅森素数:若p为素数,且Mp=2^p-1也是素数,则Mp为梅森素数。
若p为合数,Mp=2^p-1一定为合数
若p为素数,Mp=2^p-1不一定为素数
判别梅森素数
1.卢卡斯-莱默判别法:
设p为素数,Mp=2^p-1,R0=4。
Rk=(Rk-1)^2-2(mod Mp) 0<=Rk<Mp,k>=1
可以得到Rk的序列,k=0,1,2,...,p-2。
Mp为素数,当且仅当,Rp-2=0(mod Mp)
2.Miller素数测试法
我采用的是第一种,较为简单。第二种书上的没看懂,而且有些地方还印刷错误!!!。。。其实第一种对于我这个数学渣渣,我也不知道怎么证啦
详解请见《ACM-ICPC程序设计系列 数论及应用》
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <string.h> using namespace std; int t,p; bool isprime[70]; void init() { memset(isprime,true,sizeof(isprime)); for(int i=2; i*i<70; i++) { if(isprime[i]) { for(int j=i*2; j<70; j+=i) isprime[j]=false; } } } long long quickPow(long long a,int b) { long long ans=1; while(b) { if(b&1) ans=ans*a; a=a*a; b=b/2; } return ans; } //由于a*b可能会超出long long的范围,所以这里将乘法换成加法取模运算 //想法妙啊!!! long long quickPlus(long long a,long long b,long long mod) { long long ans=0; while(b) { if(b&1) ans=(ans+a)%mod; b=b/2; a=(a<<1)%mod; } return ans; } int main() { init(); scanf("%d",&t); while(t--) { scanf("%d",&p); if(isprime[p]) { long long r=4; long long Mp=quickPow(2,p)-1; long long tmp; for(int i=1; i<=p-2; i++) { tmp=quickPlus(r,r,Mp); r=((tmp-2)%Mp+Mp)%Mp; } if(!r||p==2) //2作为特判 printf("yes "); else printf("no "); } else { printf("no "); } } return 0; }