直接模拟 打表以及优化
#include <stdio.h>
#include <math.h> // 优化需要sqrt函数
#define N 10010
int prime[N];
int main()
{
int i, j, t;
int n;
scanf("%d", &n);
for (i = 2; i <= n; i++) prime[i] = 1;// 1不是素数
for (i = 2; i <= n; i ++)
{
for (j = 2; j < i; j++) // 优化将 j<i 替换为 j < sqrt(i) 即可
{
if (i % j == 0) prime[i] = 0;
}
}
for (i = 1, j = 0; i <= n; i++)
{
if (prime[i])
{
printf ("%d ", i), j++;
if (j % 5 == 0) printf ("\n");
}
}
}
普通筛法 埃拉托斯特尼(Eratosthenes)筛法
定义一个数组(除下标1外)全部置1,即全为素数
随后从下标2开始遍历全数组,若值为1,即为素数,则将此数的所有倍数在数组中的值改为0,即非素数
#include <stdio.h>
#define N 10010
int prime[N];
int main()
{
int i, j, t;
int n;
scanf("%d", &n);
for (i = 2; i <= n; i++) prime[i] = 1;// 1不是素数
for (i = 2; i <= n; i ++)
{
if (prime[i])
for (j = 2; (long long)i * j < n); j++)
{
prime[i * j] = 0;
}
}
// 输出
for (i = 1, j = 0; i <= n; i++)
{
if (prime[i])
{
printf ("%d ", i), j++;
if (j % 5 == 0) printf ("\n");
}
}
}
然而我们很容易能发现,某些数字会被重复赋值
如6,即会被2赋0,也会在循环到3时赋0
所以下面这个算法减小了这个问题的影响
线性筛法 欧拉筛法 复杂度O(n)
这个算法要增加一个数组
将原来的prime数组改名为is_prime,增加一个prime数组用于存储所有得到的素数
代码如下
#include <stdio.h>
#define N 10010
int is_prime[N];
int prime[N];
int main()
{
int i, j, t;
int n;
int count = 0;
scanf("%d", &n);
for (i = 2; i <= n; i++) prime[i] = 1;// 1不是素数
for (i = 2; i <= n; i ++)
{
if (is_prime[i]) prime[count++] = i;
for (j = 0; j < count && i*prime[j] < n; j++)
{
prime[i*prime[j]] = 0;
}
}
// 输出 有所变化,因为素数已经被存储到单独的数组里了
for (i = 0; i < count; i++)
{
printf ("%d ", i), j++;
if (j % 5 == 0) printf ("\n");
}
}
计算过程如下
i=2 ↓
isprm 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 1 1 0 1 1 1 1 1 1 1 1 1 1 1
prime 2
i=3 ↓ ↓
isprm 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 1 1 0 1 0 1 1 0 1 1 1 1 1 1
prime 2 3
i=4 ↓
isprm 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 1 1 0 1 0 1 0 0 1 1 1 1 1 1
prime 2 3
i=5 ↓ ↓
isprm 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 1 1 0 1 0 1 0 0 0 1 1 1 1 1
prime 2 3 5
i=6 ↓ ↓
isprm 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15...18
0 1 1 0 1 0 1 0 0 0 1 0 1 1 0 0
prime 2 3 5
i=7 ↓ ↓
isprm 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15...21
0 1 1 0 1 0 1 0 0 0 1 0 1 0 0 0
prime 2 3 5 7