王道计算机机试——巧妙求素数 素数筛法

王道计算机机试——巧妙求素数 素数筛法

题目描述:

输入一个整数 n(2<=n<=10000),要求输出所有从 1 到这个整数之间 (不包括 1 和这个整数 )个位为 1 的素数,如果没有则输出 -1。
输入: 输入有多组数据。 每组一行,输入 n。
输出: 输出所有从 1 到这个整数之间 (不包括 1 和这个整数 )个位为 1 的素数 (素数之 间用空格隔开,最后一个素数后面没有空格 ),如果没有则输出 -1。
样例输入:
100
样例输出:
11 31 41 61 71
来源: 2008 年北京航空航天大学计算机研究生机试真题

巧妙求素数思路

若一个数不是素数,则必存在一个小于它的素数为其的因数。这个命题的正确性是显而易见的。那么,假如我们已经获得了 小于一个数的所有素数,我们只需确定该数不能被这些素数整除,这个数即为素 数。但是这样的做法似乎依然需要大量的枚举测试工作。
正因为如此,我们可以换一个角度,在我们获得一个素数时,即将它的所有倍数均标记成非素数,这样当我们遍历到一个数时,它没有被任何小于它的素数标记为非素数,则我们确定其为素数。

解题步骤

我们按照如下步骤完成工作:
从 2 开始遍历 2 到 1000000 的所有整数,若当前整数没有因为它是某个小于 其的素数的倍数而被标记成非素数,则判定其为素数,并标记它所有的倍数为非 素数。然后继续遍历下一个数,直到遍历完 2 到 1000000 区间内所有的整数。此 时,所有没被标记成非素数的数字即为我们要求的素数。这种算法被我们称为素 数筛法。

代码

#include<iostream>
using namespace std;
int prime[10000];//保存筛得的素数
int primeSize;//保存素数的个数
bool mark[10001];//若mark[x]为true,则表示该数x已经被标为非素数
void init() {//素数筛法
	for (int i = 1; i <= 10000; i++) {
		mark[i] = false;
	}//初始化,所有数字均没被标记
	primeSize = 0;//得到的素数个数为0
	for (int i = 2; i < 10000; i++) {//依次遍历2到10000所有数字
		if (mark[i] == true) continue;//若该数字已经被标记过,则跳过
		prime[primeSize++] = i;//否则又得到一个新素数
		for (int j = i * i; j <= 10000; j += i) {//并将该数的所有倍数标记成非
			mark[j] = true;
		}
	}
}
int main() {
	init();//在程序一开始首先取得2到10000中所有素数
	int n;
	while (cin >> n) {
		bool isOutput = false;//判断是否输出了符合条件的数字
		for (int i = 0; i < primeSize; i++) {//依次遍历得到的所有素数
			if (prime[i] < n && prime[i] % 10 == 1) {//测试当前素数是否符合条件
				if (isOutput == false) {//若当前输出为第一个输出的数字,则标记已经输出了
					//符合条件的数字,且该数字前不输出空格
					isOutput = true;
					cout << prime[i];
				}
				else cout << ' ' << prime[i];//否则在输出这个数字前输出一个空格
			}
		}
		if (isOutput == false) {//若始终不存在符合条件的数字
			cout << '无';
		}
		else cout << endl;
	}
	return 0;
}

发布了12 篇原创文章 · 获赞 12 · 访问量 162

猜你喜欢

转载自blog.csdn.net/xyzxyzxyz1999/article/details/105306719