质数-筛法取质数

118 阅读1分钟

题目(AcWing868 筛质数)

给定一个正整数 nn,请你求出 1∼n1∼n 中质数的个数。

输入格式

共一行,包含整数 nn。

输出格式

共一行,包含一个整数,表示 1∼n1∼n 中质数的个数。

数据范围

1≤n≤1061≤n≤106

输入样例:

8

输出样例:

4

埃氏筛法

思路

i从2 ~ n遍历,如果i是质数,将其存下来,然后就筛掉i的倍数的数,这样遍历完,剩下来的数都是质数。这是为什么呢?假设一个数p,2 ~ p-1中没有一个数将p删掉,则p不是2 ~ p-1中任何一个数的倍数,其一定就是质数。质数定理:1~n中有n/lnn个质数,所以该算法的时间复杂度是O(nloglogn)

代码

#include<iostream>

using namespace std;

const int N = 1000010;
int primes[N];
bool st[N];

int cnt = 0;

void get_primes(int n) 
{
    for (int i = 2; i <= n; i ++ )
    {
        if (!st[i])
        {
            primes[cnt ++ ] = i;
            for (int j = i; j <= n; j += i) st[j] = true;
            
        }
    }
}

int main()
{
    int n;
    cin >> n;
    get_primes(n);
    cout << cnt << endl;
    return 0;
}

线性筛法

思路

n只会被它的最小质因子筛掉。

  1. i % primes[j] == 0。primes[j]一定是i的最小质因子, primes[j]一定是primes[j] * i的最小质因子
  2. i % primes[j] != 0。primes[j]一定小于i的所有质因子,primes[j]也一定是primes[j] * i的最小质因子
  3. 对于一个合数x,pj是其最小质因子,当i枚举到x/pj时,就可以筛掉。

代码

#include<iostream>

using namespace std;

const int N = 1000010;
int primes[N];
bool st[N];

int cnt = 0;

void get_primes(int n) 
{
    for (int i = 2; i <= n; i ++ )
    {
        if (!st[i]) primes[cnt ++ ] = i;
        for (int j = 0; primes[j] <= n / i; j ++ )
        {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0) break;
        }
    }
}

int main()
{
    int n;
    cin >> n;
    get_primes(n);
    cout << cnt << endl;
    return 0;
}