提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
一、素数筛选法
1.介绍:假设所有待判断的数字的上限是L,声明一个长度为L+1的布尔数组A[L+1]。用这个数组来表示对应下标的数字是不是素数。起初,将数组所有成员标记为1,然后按照某种方法将其中的非素数都标记为0即可
2.实现:
(1)首先声明一个布尔数组isprime[L+1], 先将isprime[0],isprime[1]置0,再将布尔数组里所有除了2以外的偶数判断元素置false,这样我们判断的数据就减少了一半。
(2)从i = 3开始,将小于等于L 的每一个j = i*i的奇数倍的isprime[j]置0;筛去所有素数的倍数,剩余则为素数。
3.代码:
#include <stdio.h>
#include <math.h>
#include <stdbool.h>
#define MAXN 100
int prime[MAXN] = {0};//素数表
bool is_prime[MAXN + 1] = {0};
int Sieve(int n)
{
int p = 0;
int index = 0;
is_prime[0] = is_prime[1] = false;
is_prime[2] = true;
for (index = 3; index <= n; index += 2) //奇数置ture
{
is_prime[index] = true;
}
prime[0] = 2;
for (index = 3; index <= n; index += 2)
{
if (is_prime[index])
{
prime[++p] = index;
for (int i = index * index; i <= n; i += index * 2)
{
is_prime[i] = false;
}
}
}
return p + 1;
}
int main(int argc, char const *argv[])
{
int all_num = 0;
all_num = Sieve(20);
printf("素数个数:%d\r\n", all_num);
for (int i = 0; i < all_num; i++)
{
printf("%d ", prime[i]);
}
printf("\r\n");
return 0;
}
结果:
素数个数:8
2 3 5 7 11 13 17 19
二、点灯案例
1.案例
有n盏灯,编号为1~n,第1个人把所有灯打开,第2个人按下所有编号为2 的倍数的开关(这些灯将被关掉),第3 个人按下所有编号为3的倍数的开关(其中关掉的灯将被打开,开着的灯将被关闭),依此类推。一共有k个人,问最后有哪些灯开着?输入:n和k,输出开着的灯编号。k≤n≤1000
输入 输入一组数据:n和k
输出 输出开着的灯编号
2.思路
此案例与素数筛选法有些相似,设每个灯一开始的状态为false,从第i = 0个人开始,直到i < k, 将每个 i 的倍数取反,看每个灯取反多少次即得其最终状态。
3.代码
#include <stdio.h>
#include <stdbool.h>
int PrintfState(int n, int k)
{
int num = 1;
int person = 1;
bool state = false;
for (num = 1; num <= n; num++)
{
state = false;
for (person = 1; person <= k; person++)
{
if (!(num % person))
{
state = !state;
}
}
if (state)
{
printf("%d ", num);
}
}
printf("\r\n");
return 0;
}
int main(int argc, char const *argv[])
{
int n = 0, k = 0;
printf("请输入参数:");
scanf("%d,%d", &n, &k);
printf("亮灯编号:");
PrintfState(n, k);
return 0;
}
运行:
请输入参数:8,4
亮灯编号:1 4 5 6 7 8