数论 筛质数

AcWing 868. 筛质数
由于我是我们队的数论选手,寒假刷题会略偏向于数论方面QWQ,在此记录 2021-01-12 刷题打卡~

在这里插入图片描述

线性筛法

核心思想:
保证了每个数一定是被它的最小质因子筛掉的,时间复杂度 O(n)
AC代码:

#include <bits/stdc++.h>

#define ll long long
using namespace std;
const int N = 1e6 + 10;

int primes[N];
bool st[N];

void get_primes(ll n) {
    
    
    int cnt = 0;
    for (int i = 2; i <= n; i++) {
    
    
        if (!st[i]) {
    
    
            primes[cnt++] = i;
            // primes数组 存 筛选出来的质数
        }
        // 原理:筛除数的时候利用这个数的 最小质因子
        // 每个数n,只会被它的最小质因子筛除
        for(int j = 0; primes[j] <= n/i; j++) {
    
    
            st[primes[j] * i] = true;
            if(i % primes[j] == 0)  // 这个判断意味着 primes[j] 一定是 i 的最小质因子 (从小到大的枚举)
                break;              // 同时 primes[j] 也一定是 primes[j] * i 的最小质因子
        }
    }
    cout << cnt << endl;  // cnt 代表筛选出的 质数数量
}

int main() {
    
    
    ll n;
    while (~scanf("%lld", &n)) {
    
    
        if (n == 1) {
    
    
            cout << 0 << endl;
            continue;
        }
        get_primes(n);
        // 如有需要,可以打出筛选出来的质数 primes数组
    }
    return 0;
}

朴素筛法

在这里插入图片描述
AC代码:

#include <bits/stdc++.h>

#define ll long long
using namespace std;
const int N = 1e6 + 10;

int primes[N];
bool st[N];

void get_primes(ll n) {
    
    
    int cnt = 0;
    for (int i = 2; i <= n; i++) {
    
    
        if (!st[i]) {
    
    
            primes[cnt++] = i;
            // primes数组 存 筛选出来的质数
        }
        // 循环 筛选出 倍数
        for (int j = i + i; j <= n; j += i) {
    
    
            st[j] = true;
        }
    }
    cout << cnt << endl;  // cnt 代表筛选出的 质数数量
}

int main() {
    
    
    ll n;
    while (~scanf("%lld", &n)) {
    
    
        if (n == 1) {
    
    
            cout << 0 << endl;
            continue;
        }
        get_primes(n);
        // 如有需要,可以打出筛选出来的质数 primes数组
    }
    return 0;
}

埃式筛法

埃式筛法是朴素筛法的一个优化,时间复杂度为 O(nloglogn),即只用筛除所有所有质数的倍数
在这里插入图片描述
AC代码:

#include <bits/stdc++.h>

#define ll long long
using namespace std;
const int N = 1e6 + 10;

int primes[N];
bool st[N];

void get_primes(ll n) {
    
    
    int cnt = 0;
    for (int i = 2; i <= n; i++) {
    
    
        if (!st[i]) {
    
    
            primes[cnt++] = i;
            // primes数组 存 筛选出来的质数
            // 循环 筛选出 倍数
            for (int j = i + i; j <= n; j += i) {
    
    
                st[j] = true;
            }
        }
    }
    cout << cnt << endl;  // cnt 代表质数数量
}

int main() {
    
    
    ll n;
    while (~scanf("%lld", &n)) {
    
    
        if (n == 1) {
    
    
            cout << 0 << endl;
            continue;
        }
        get_primes(n);
        // 如有需要,可以打出筛选出来的质数 primes数组
    }
    return 0;
}

总结:线性筛法时间复杂度最低,建议使用

而埃式筛法更多的是提供一种解题的思路,在其他的一些算法题中也会用到。

猜你喜欢

转载自blog.csdn.net/qq_45654671/article/details/112518935