埃氏筛法
素数的定义:素数就是除了1和本身之外没有其他的约数,所以有约数的都不是素数。
埃氏筛法的主要思想是去除所有质数的倍数如图:
这张图片就包含了筛法的主要思想
下面来代码实现叭
#include <stdio.h>
#include <string.h>//memset函数的头文件
int l[10005];//用于标记数字
int p[10005], num = 0;//用于储存素数,记录素数个数
int find_prime(int n)
{
for(int i = 2; i <= n; i++)
{
if(!l[i])//0为素数,1为合数
{
p[num++] = i;
for(int j = i*2; j <= n; j += i)//排数素数的倍数
{
l[j] = 1;
}
}
}
return num;
}
int main(void)
{
int n, ans;
scanf("%d", &n);
memset(l, 0, sizeof(l));//0为素数,1为合数
memset(p, 0, sizeof(p));//清空l,p数组
l[0] = 1;
l[1] = 1;//排除特殊情况
ans = find_prime(n);
for(int i = 0; i < ans; i++)
{
printf("%d ", p[i]);//输出素数
}
printf("\n%d", ans);
return 0;
}
下面为输出
欧拉筛法
欧拉筛法的时间复杂度为O(n),所以又称为线性筛
欧拉筛法的主要思想与埃氏筛法相同,是埃氏筛法的优化,我们知道30 = 2 * 15 = 3 * 10 = 5 * 6所以会造成一个数被多次晒出从而造成效率降低,欧拉筛法就是弥补这个不足
主要思想:算数基本定理:任何一个大于1的自然数,如果n不为质数,那么n可以唯一分解成有限个质数的积
用自己的话说:任何数的合数能表示为多个素数的积,那么一个合数必定会有一个最小质因子,我们只需让这一个最小质因子筛去该数即可,我们通过这个最小质因子的判断就可确定什么时候不用筛下去了,用30举例,筛出的素数为从小到大排列,我们只需用2筛去30即可,也就是说如果30%2 == 0的话证明该数已被筛出直接跳出循环即可
下面是代码演示:
#include <stdio.h>
#include <string.h>//memset函数的头文件
int l[10005];//用于标记数字
int p[10005], num = 0;//用于储存素数,记录素数个数
int find_prime(int n)
{
num = 0;
for(int i = 2; i <= n; i++)
{
if(!l[i])//0为素数,1为合数
{
p[num++] = i;
}
for(int j = 0; j < num && p[j] * i <= n; j++)
{
l[p[j] * i] = 1;
if(i % p[j] == 0) break;
}
}
return num;
}
int main(void)
{
int n, ans;
scanf("%d", &n);
memset(l, 0, sizeof(l));//0为素数,1为合数
memset(p, 0, sizeof(p));//清空l,p数组
l[0] = 1;
l[1] = 1;//排除特殊情况
ans = find_prime(n);
for(int i = 0; i < ans; i++)
{
printf("%d ", p[i]);//输出素数
}
printf("\n%d", ans);
return 0;
}
输出结果