引言
埃拉托斯特尼筛法,简称埃氏筛,是一种由希腊数学家埃拉托斯特尼所提出的一种简单检定素数的算法。在了解这种算法之前,先来看看一般素数求法。
素数定义
质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数(规定1既不是质数也不是合数)。
【题目】
给定整数 n
,返回 所有小于非负整数 n
的质数的数量 。
示例 1:
输入:n = 10
输出:4
解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。
示例 2:
输入:n = 0
输出:0
示例 3:
输入:n = 1
输出:0
一般方法,枚举法
我们设定一个数为x,根据质数的定义判断x是否为质数,我们看它能否被2、3、4······、x-1整除,如果它不能被其中任何一个整数整除,则这个数就是质数。
#include<stdio.h>
int sushu(int x);
int main()
{
int n;
int i, count = 0;
scanf("%d",&n);
for(i = 2; i < n; i++)
{
count += sushu(i);
}
printf("%d",count);
return 0;
}
int sushu(int x)
{
for(int i = 2; i*i <= x; i++){
if(x % i == 0)
return false;
}
return true;
}
然而,枚举没有考虑到数与数的关联性,代码难以再继续优化时间复杂度。接下来,我们来学习一种新的算法——埃筛法。
埃拉托斯特尼筛法,简称埃氏筛,是一种由希腊数学家埃拉托斯特尼所提出的一种简单检定素数的算法。要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的倍数剔除,剩下的就是素数。先考虑这样一个事实:如果 x 是质数,那么大于 x 的 x 的倍数 2x,3x… 一定不是质数,我们可以从这里入手。设 sushu[i] 表示数 i 是质数,如果是质数则为 1,否则为 0。从小到大遍历每个数,如果这个数为质数,则将其所有的倍数都标记为合数(除了该质数本身),即 0,这样在运行结束的时候我们即能知道质数的个数。
算法思想:给出要筛数值的范围,找出其以内的素数。先用2去筛,即把2留下,把2的倍数剔除掉;再用下一个质数3去筛,把3留下,把3的倍数剔除掉;接下去用下一个质数5筛,把5留下,把5的倍数剔除掉;不断重复下去......
#include<stdio.h>
int main()
{
int n;
int i, j, count = 0;
scanf("%d",&n);
int num[n] = {0};//先全部置 0 ,假设全为素数,后面判断若为合数则置 1 。
if(n<2)
printf("0");
for(i = 2; i < n; i++)
{
if(!num[i])//num[i]为 0 进入循环
{
count += 1;
if ((long long)i * i < n) {
for (j = i * i; j < n; j += i) {
num[j] = 1;
}
}
}
}
printf("%d",count);
return 0;
}