现在的位置: 首页 > 综合 > 正文

NPOJ(BETA) 1021 梅森素数(NWPU SRM of 2013.Dec D) 简单数学

2013年03月11日 ⁄ 综合 ⁄ 共 1780字 ⁄ 字号 评论关闭

题目——梅森素数

时间限制:1000ms 内存限制:65536KB 

题目描述

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

输入

有1组测试数据。
第一行是一个正整数 T ,表示这一组测试数据的总个数。
接下来的每一行都是1个 p 的值,这里2 ≤ p ≤ 20。
这些总共会有 T 行。
	

输出

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

示例输入

2
2
7
	

示例输出

yes
yes

题解

首先先给大家道个歉,由于我以为大家都打开了PC^2,所以就自作主张的在PC^2里面公示了题面更改和“请刷新浏览器”的信息,结果我错了=。=很多人都没看到=。=真惨。。。先给大家说声对不起了,第一次出题玩这个的确不熟练。。。

然后是正事:

我们都知道朴素的素数判断是O(根号n)的时间复杂度,就是说从3开始(偶数除了2以外全是合数,所以单独考虑2就行了),一直到根号n,进行遍历即可。那么对于这道题目,p最大20,也就是说最大的数据是2^20,可以在2^10次计算下完成,2^10 = 1024,也就是1000次运算,时间开销非常小。即便是纯暴力求解也毫无压力,因为我给的数据非常的弱。

发散一下:如果是多组数据但是不改变p的范围,最优的方法是打表法,我的标程就是这样的方法,同时用了一个小的优化,把时间复杂度优化到了,我相信你们能看出来的是吧!

接着发散一下,如果改变p的范围,那就要用到米勒罗宾测试来求解了,具体的请自行百度吧!

代码示例

/****
	*@PoloShen
	*Title:D - NWPU SRM of 2013.Dec
	*/
#include <iostream>
#include <vector>
#include <cstdio>
#include <cmath>
using namespace std;

int Power(int a, int r){//整数乘方函数
	if (r == 0) return 1;
	else{
		int res = 1;
		for (int i = 0; i < r; ++i) res *= a;
		return res;
	}
	return a;
}
inline int Gener(int p){//生成梅森数
	return Power(2, p) - 1;
}
vector<int> Prime;int sz;
bool ans[25];
void set_Prime(){//建立素数表
	Prime.clear();Prime.push_back(2);
	for (int i = 3; i < 1100; i+=2){
		bool flag = 1;
		for (int j = 2; j < sqrt((double)i); ++j){
			if ((i % j) == 0){flag = 0;break;}
		}
		if (flag) Prime.push_back(i);
	}
	sz = Prime.size();
	return;
}
bool judge(int mp){//利用素数表判断素数
	for (int i = 0; i < sz; ++i){
		if (mp == Prime[i]) return 1;		//如果与素数相同,即为素数
		if ((mp % Prime[i]) == 0) return 0;	//能够整除一素数,即为合数
	}
	return 1;
}
void set_table(){//建立梅森数表
	for (int p = 2; p < 21; ++p){
		int mp = Gener(p);
		ans[p] = judge(mp);
	}
	return;
}
void solve(){//主要输入输出程序
	int p;scanf("%d", &p);
	if (ans[p]) printf("yes\n");
	else printf("no\n");
	return;
}
int main(){
	set_Prime();
	set_table();
	int T;scanf("%d", &T);
	while (T--){
		solve();
	}
    return 0;
}

标准输入

标准输出

20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
20
yes
yes
no
yes
no
yes
no
no
no
no
no
yes
no
no
no
yes
no
yes
yes
no

抱歉!评论已关闭.