素数筛法【九度教程第51题】

题目描述:

输入一个整数 n(2<=n<=10000),要求输出所有从 1 到这个整数之间(不包括1和这个整数)个位为 1 的素数,如果没有则输出-1。

输入:

输入有多组数据。 每组一行,输入 n。

输出:

输出所有从1到这个整数之间(不包括1和这个整数)个位为1的素数(素数之间用空格隔开,最后一个素数后面没有空格),如果没有则输出-1。

样例输入:

100

样例输出:

11 31 41 61 71

来源:
2008 年北京航空航天大学计算机研究生机试真题

思路

素数筛法:用筛法求素数的基本原理,是把从1开始的某一范围内的正整数从小到大顺序排列,逐步筛掉非素数留下素数。
代码思路:

  1. 定义素数筛法子函数,求出所有在范围内的素数
  2. 调用子函数从素数数组中取出在范围内的所有满足条件的素数打印出来

### 代码
#include<stdio.h>
#include<math.h>
#define MAXSIZE 10000
int primenum = 0;
int prime[MAXSIZE]; //存放素数
int flags[MAXSIZE + 1]; 
// 0代表为素数 1代表不为素数 
// 注意这里初始化的长度 是为了比较方便的存储 例如flags[1]就代表了1是否为素数
//一定要是全局变量
void init() {
	for (int i = 1; i < MAXSIZE + 1; i++) {
		flags[i] = 0; //首先初始化为0 先认为1-10000都是素数
	}
	for (int j = 2; j < MAXSIZE + 1; j++) { // 素数筛法 从2开始
		if (flags[j] == 1) // 如果该数是某数的倍数 说明不是素数 则筛选下一个数
			continue;
		else {
			prime[primenum] = j;
			primenum++; 
			for (int k = j * j; k < MAXSIZE + 1; k+=j) {
				flags[k] = 1;//倍数不是素数
			}
		}
	}
}
int main() {
	init();
	int bound; 
	while (scanf("%d", &bound) != EOF) {
		bool firstout = true; //当前输出是第一个输出 注意一定要放到循环里面!!
		int m = 0; //局部变量!! 每个数都要从头开始!!
		while (prime[m] < bound ) {
			if (prime[m] % 10 == 1 ) {//末尾为1
				if (firstout == true) {
					printf("%d", prime[m]);
					firstout = false;
				}
				else {
					printf(" %d", prime[m]);
				}
			}
			m++;
		}

		if (firstout == true) {//如果还为true的话说明没改过 也就是没有进入循环找到满足条件的
			printf("-1\n");
		}
		else printf("\n");
	}
	return 0;
}

代码里的注意点如下:

  1. 全局变量的定义:包括素数个数primenum、素数数组prime、标志数组flags,因为有一个子函数,想要在主函数内继承子函数的结果,就需要定义全局变量
  2. 局部变量的定义:主函数中的mfirstout,都是在每个不同输入的情况下需要重新计算的,不能在不同输入时有继承效果,一定要注意该变量的作用范围!
  3. 数组长度的定义flags[MAXSIZE+1]因为flags是用来标志对应的数是否为素数,这里定义为+1是为了取索引的方便:数字2是否为素数——flags[2]而不是flags[1]这样
  4. 筛法小技巧:判定i为素数,要标记其所有倍数为非素数时,没有从2*i开始标记,而是直接从i*i开始标记,因为i*k(k<i)一定在之前就已经标记过了,因为它还是k的倍数。
发布了23 篇原创文章 · 获赞 26 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Scofield971031/article/details/89400531