NEFU 120 梅森素数(梅森数素数判定--Lucas-Lehmer测试判定)

梅森素数

Problem : 120

Time Limit : 1000ms

Memory Limit : 65536K

description



由于梅森学识渊博,才华横溢,为人热情以及最早系统而深入地研究2p-1 型的数(其中p为素数),为了纪念他,数学界就把这种数称为“梅森数”;并以Mp 记之(其中M为梅森姓名的首字母),即Mp=2p-1 。如果梅森数为素数,则称之为“梅森素数”。 比如p=2,3,5,7时,Mp都是素数,但211-1 不是素数 。现在请你求出前N个梅森素数。


input


有多组测试数据。
第一行是一个正整数T,表示测试数据的组数。接下来每组1个数p的值,这里2<= p <= 62。

output



对于每组测试数据,判断Mp 是不是梅森素数,是就输出“yes ”,否就输出“no”,输出后要换行。


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

,如果
,如果
.
.
.

这个序列的开始几项是41419437634,
... (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

NEFU 120 梅森素数(梅森数素数判定--Lucas-Lehmer测试判定)的相关文章

素数判定 费马测试

;; Fermat's Little Theorem: ;; If N is a prime number and A is any positive integer less than N,  ;; then A raised to the N-th power is congruent to A modulo N ;; Two numbers are said to be congruent modulo N if they both ;; have the same remainder w

判断2~100的所有素数,是素数输出并打印

/** * 判断2~100的所有素数,是素数输出并打印 * 10个一换行 */ public class IsPrime { public static void main(String[] args) { int num = 100; printPrime(num); } public static void printPrime(int num) { int count = 0; //记素数的个数 /*检验2~num之间所有的数字*/ for (int i = 2; i <= num; i+

NEFU 2 - 猜想 - [筛法求素数]

题目链接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=2 Time Limit:3000ms Memory Limit:65536K Description 哥德巴赫(Goldbach ]C.,1690.3.18~1764.11.20)是德国数学家:出生于格奥尼格斯别尔格(现名加里宁城):曾在英国牛津大学学习:原学法学,由于在欧洲各国访问期间结识了贝努利家族,所以对数学研究产生了兴趣:曾担任中学教师.1725年,到了

素数判定(米勒测试定理-费马小定理+快速乘)

1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<vector> 7 #include<ctime> 8 #define llg long long 9 llg i,j,k,x,n,m; 10 using namespace std; 11 ll

素数专题——素数筛法

关于素数的判断,大家最常用的方法估计就是循环判断到sqrt(n)的方法了:(直接上代码) bool isprime(int n) { for(int i=2;i<=sqrt(n);i++) { if(n%i==0) return false; } return true; } 这种素数的判断方法的确直观,但这种算法只对较小数据量适用,当数据量较大时,该方法就不再适用于素数的判定了.因此,我们此处引入一种新的算法——素数筛法. 首先介绍一下什么叫素数筛法: 假设所有待判断的数字的上限是L,声明一个

最大公约数,最小公倍数,素数,素数筛

最大公约数 a.b的最大公约数是b,a%b的公约数,如果有一个等于0,最大公约数是a int gcd(int a,int n){ if (b==0) return a; else return gcd(b,a%b); } 或 return b!=0 ? gcd(b,a%b):a; 最小公倍数 是两数的乘积除以他们的最大公约数 素数筛 输出2-10000之间的所有素数 从2开始遍历,标记每个数的所有倍数为非素数 void sushu(){ for (int i=0;i<10000;i++){ ma

hdu2098 分拆素数和 素数筛

将一个偶数拆成两个素数的和,欧拉筛暴力 1 #include<stdio.h> 2 #include<string.h> 3 #define N 10001 4 int prime[10001]; 5 bool check[10001]; 6 int n,i,ans,tot=0,j; 7 8 void EulerPrime(){ 9 memset(check,false,sizeof(check)); 10 for(i=2;i<=N;i++){ 11 if(!(check[i

HDU 2098 分拆素数和(素数)

http://acm.hdu.edu.cn/showproblem.php?pid=2098 题意: 给你一个偶数,问你这个偶数有多少种方式能由两个不同的素数构成? 分析: 首先求出10000以内的所有素数. 如果这个偶数X能有两个不同的素数构成,那么一定一个小于(X/2-1). 只要从小到大枚举这个比较小的素数a,然后看看X-b是否是素数即可得到一种组合方式. 依次统计所有组合方式即可. AC代码: #include<cstdio> #include<algorithm> #in

hdu2098分拆素数和(素数+暴力)

分拆素数和 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 48614    Accepted Submission(s): 21227 Problem Description 把一个偶数拆成两个不同素数的和,有几种拆法呢? Input 输入包含一些正的偶数,其值不会超过10000,个数不会超过500,若遇0,则结束. Output 对应