#include <stdio.h>
#include <math.h>
// 求2-n里面的所有素数,要求n大于等于2
int main()
{
int n = 10000;
int N[n + 1];//存储0~n,
for (int i = 0; i <= n; i++)
{
N[i] = i;
}
int sum = 1;//对1-n合数计数,这里把1看作了合数
int a[n / 2];
int L = sqrt(n); // 这里考虑改进,写一个int(sqrt(int n))函数
for (int i = 2; i <= L;)
{
int flag = 0;
int L2 = n / i;
for (int k = i; k <= L2; k++)
{
if (N[k])//这里非0则代表没有被前面的小素数整除过
{
a[flag] = k;//存储被i整除且没有被前面小素数整除过的数
flag++;//被整除说明是合数,所以计数
}
}
sum = sum + flag;//还是计数
for (int j2 = 0; j2 < flag; j2++)
{
N[a[j2] * i] = 0;//把2-n里面被i整除且没有被前面小素数整除过的数变为0
}
//上面两个for循环保证了两个质数不会排除相同的数,其实就是不需要做重复乘法,改为了比较。
//代码变长了,但是时间复杂度降低了
int j = i + 1;
while (1)
{
if (N[j])//寻找下一个质数
{
i = N[j];
break;
}
else
{
j++;
}
}
}
printf("primes <= %d are:\n", n);
for (int i = 2; i <= n; i++)
{
if (N[i])
{
printf("%d ", N[i]);
}
}
printf("\n");
printf("primes toal is %d", n - sum);
return 0;
}
对一般的埃氏筛法进行了改进,对于当前素数p,因为被前面的小素数整除过的都赋值为0,所以只需要一个逻辑判断就可以防止两个素数排除掉同一个数的情况,这里两个for循环是为了把被同一个素数整除的数一同变为0,保证被变为0时最小素因子相同。改进的本质是把一部分乘法运算变成了逻辑运算和赋值运算。