梅森素数 |
|||
|
|||
description |
|||
|
|||
input |
|||
有多组测试数据。 第一行是一个正整数T,表示测试数据的组数。接下来每组1个数p的值,这里2<= p <= 62。 |
|||
output |
|||
|
|||
sample_input |
|||
2 2 7 |
|||
sample_output |
|||
yes yes |
思路:显然n=2^p-1当p不是素数时n不是梅森数,显然不是素数(可以分解因式反证)
当p是素数即n是梅森数时,需要判定n是不是素数,可以用Lucas-Lehmer测试判定法
涉及知识:
卢卡斯-莱默检验法原理是这样:令梅森数 Mp = 2p? 1作为检验对象(预设p是素数,否则Mp就是合数了)。定义序列{si }:所有的i ≥ 0
-
-
,如果; ,如果。
-
- .
- .
- .
这个序列的开始几项是4, 14, 194, 37634,
... (OEIS中的数列A003010)
那么Mp是素数当且仅当
否则, Mp是合数。sp ?
2模Mp的余数叫做p的卢卡斯-莱默余数。
用程序算出Sp-2即可,要注意的是p=2时,不能用这个判定方法,特判一下即可
//Accepted 800k 4ms C++ (g++ 3.4.3) 692 #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; ll T,p; ll multi(ll a,ll b,ll mod)//手写乘法计算,因为直接乘会溢出long long { ll ans=0; while(b) { if(b&1) ans=(ans+a)%mod; b>>=1; a=(a<<1)%mod; } return ans; } int main() { scanf("%lld",&T); while(T--) { scanf("%lld",&p); ll n=((ll)1<<p)-1; ll r=4; if(p==2) puts("yes");//特判 else { while((--p)!=1) r=(multi(r,r,n)-2+n)%n; if(r%n==0) puts("yes"); else puts("no"); } } return 0; }
时间: 2024-12-25 18:11:52