您的位置:首页 > 其它

nefu 120 梅森素数

2014-02-16 18:57 561 查看
题意:给出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程序设计系列 数论及应用》

#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\n");
else
printf("no\n");
} else {
printf("no\n");
}
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: