【数学】素数筛和线性筛

方法一:暴力

时间复杂度O(n * sqrt(n))

include<stdio.h>
int is_prime(int x)
{
    for (int i=2; i*i < x; i++)
        if (x % i == 0)return 0;
    return 1;
}
int main()
{
    int num,prime_num = 0;
    for (num = 1; prime_num<= 1001;)
    {
        num++;
        prime_num += is_prime(num);
    }
    printf("%d
",num);
    return 0;
}

方法二:素数筛

时间复杂度O(n * sqrt(loglogn))

总体思想:素数的倍数一定是合数,用已知的素数标记合数

#include<bits/stdc++.h>
using namespace std;
#define MAX_N 1000
int prime[MAX_N + 5] = {0};

int main()
{

   for (int i = 2; i <= MAX_N; i++){
    if (!prime[i]){
        for (int j = 2*i; j<MAX_N; j += i){
            prime[j] = 1;
        }
    }
   }
   for (int i = 2; i <= MAX_N; i++)
        if(!prime[i]) prime[++prime[0]] = i;
   int n;
   while (~scanf("%d",&n))
   {
       printf("第%d个素数是%d
",n,prime[n]);
   }
}

变形一:求1-1000内每个数字最小的素因子

#include<bits/stdc++.h>
using namespace std;
#define MAX_N 1000
int prime[MAX_N + 5] = {0};

int main()
{

   for (int i = 2; i*i <= MAX_N; i++){
    if (!prime[i]){
        for (int j = i; j <= MAX_N; j += i){
            if (!prime[j]) prime[j] = i; ///只有第一次赋值,保证最小
        }
    }
   }

   int n;
   while (~scanf("%d",&n))
   {
       printf("%d的最小素因子是%d
",n,prime[n]);
   }
}

变形·二:求1-1000内每个数字最大的素因子

#include<bits/stdc++.h>
using namespace std;
#define MAX_N 1000
int prime[MAX_N + 5] = {0};

int main()
{

   for (int i = 2; i*i <= MAX_N; i++){
    if (!prime[i]){
        for (int j = i; j <= MAX_N; j += i){
            prime[j] = i;/// 覆盖
        }
    }
   }

   int n;
   while (~scanf("%d",&n))
   {
       printf("%d的最大素因子是%d
",n,prime[n]);
   }
}

方法三:线性筛

时间复杂度O(n )

总体思想:

线性筛是基于素数筛的改进,
在素数筛的时候
6被2标记后,又被3标记...
15被3标记后,又被5标记...
30被2标记后,又被3标记,又又被5标记...
会有重复标记造成的浪费
线性筛的时候

M              为遍历数的代表
Min_p (M)       为M的最小素因子
Set_p (n)      为从2到n的素数集合

第一层循环是:遍历M
第二层循环是:遍历这个Set_p (Min_p (M))的集合元素
eg:
M == 15
Min_p (M) == 3
Set_p (Min_p (M)) = {2,3}
标记的数为:30,45
75 会是 它最小的素因子5 在M为25 时标记到的

#include<bits/stdc++.h>
using namespace std;
#define MAX_N 000
int set_prime[MAX_N + 5] = {0};

int main()
{

    for (int m = 2; m <= MAX_N; m++)
    {
        if (!set_prime[m]) set_prime[++set_prime[0]] = m;
        for (int j = 1; j <= set_prime[0] && set_prime[j] * m <= MAX_N; j++)
        {
            set_prime[set_prime[j] * m] = 1;
            if (m % set_prime[j] == 0) break;///功能:保持 prime[j]  一定小于 i 的最小素因子
        }
    }
    int n;
    while (~scanf("%d",&n))
    {
        printf("第%d个的素数是%d
",n,set_prime[n]);
    }
}
原文地址:https://www.cnblogs.com/sxy-798013203/p/7790067.html