[算法]—素数筛法

埃氏筛法

素数的定义:素数就是除了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;
}

输出结果
在这里插入图片描述

发布了20 篇原创文章 · 获赞 2 · 访问量 940

猜你喜欢

转载自blog.csdn.net/zhbbbbbb/article/details/103529181