【算法】数论——筛质数(线性筛法)

题目

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

输入格式

共一行,包含整数 n。

输出格式

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

数据范围

1 ≤ n ≤ 10^6

思路

朴素筛法
做法 :把2~(n-1)中的所有的数的倍数都标记上,最后没有被标记的数就是质数.
原理 :假定有一个数p未被2~(p-1)中的数标记过,那么说明,不存在2~(p-1)中的任何一个数的倍数是p,也就是说p不是2~(p-1)中的任何数的倍数,也就是说2~(p-1)中不存在p的约数,因此,根据质数的定义可知:p是质数.
时间复杂度:约为O(nlogn);

埃氏筛(稍加优化版的筛法)
质数定理 :1~n中有n/lnn个质数.
原理 :在朴素筛法的过程中只用质数项去筛.
时间复杂度:粗略估计:O(n).实际:O(nlog(logn)).1~n中,只计算质数项的话,"1/2+1/3+1/4+1/5+...+1/n"的大小约为log(logn)。

线性筛法 核心 :1~n内的合数p只会被其最小质因子筛掉.
原理:1~n之内的任何一个合数一定会被筛掉,而且筛的时候只用最小质因子来筛,然后每一个数都只有一个最小质因子,因此每个数都只会被筛一次,因此线性筛法是线性的.

注意:

1、枚举到 i 的最小质因子的时候就会停下来,即" if(i%primes[j]==0) break ; "。

2、因为从小到大枚举的所有质数,所以当" i % primes[j] != 0 "时,primes[ j ]一定小于 i 的最小质因子,而且 primes[j] 一定是primes[j] * i的最小质因子。

3、关于for循环的解释:

注:首先要把握住一个重点:我们枚举的时候是从小到大枚举的所有质数

(1)当i%primes[j]==0时,因为是从小到大枚举的所有质数,所以primes[j]就是i的最小质因子,而primes[j]又是其本身primes[j]的最小质因子,因此当i%primes[j]==0时,primes[j]是primes[j] * i的最小质因子。

(2)当 i%primes[j]!=0 时,因为是从小到大枚举的所有质数,且此时并没有出现过有质数满足i%primes[j] == 0,因此此时的primes[j]一定小于i的最小质因子,而primes[j]又是其本身primes[j]的最小质因子,所以当i%primes[j]!=0时,primes[j]也是primes[j] * i的最小质因子。

(3)综合1,2得知,在内层for循环里面无论何时,primes[j]都是primes[j] * i的最小质因子,因此 "st[primes[j * i] = true"语句就是用primes[j]i这个数的最小质因子来筛掉这个数。

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1000010;
int primes[N],cnt;
bool st[N];// 储存该值i是不是为非质数

void get_primes(int n)
{
    for(int i = 2;i <= n; i ++)// 依次判断2~n是否为质数
    {
        if(!st[i]) primes[cnt ++] = i;// 如果该数是质数则将其储存起来,如果不是质数则不储存
        for(int j = 0;primes[j] <= n / i; j ++)// 筛掉是i的primes[j]倍的所有合数
        {
            st[primes[j] * i] = true;// 确保每个合数是被他最小的质因子筛掉的
            if(i % primes[j] == 0) break;// primes[j]一定是i的最小质因子
            //p[j]一定是i的最小质因子,pj也一定是pj*i的最小质因子
        }
    }
}

int main()
{
    int n;
    cin >> n;
    get_primes(n);
    cout << cnt << endl;
    return 0;
}
相关推荐
易码智能7 分钟前
【EtherCATBasics】- KRTS C++示例精讲(2)
开发语言·c++·kithara·windows 实时套件·krts
ཌ斌赋ད13 分钟前
FFTW基本概念与安装使用
c++
带多刺的玫瑰20 分钟前
Leecode刷题C语言之切蛋糕的最小总开销①
java·数据结构·算法
巫师不要去魔法部乱说30 分钟前
PyCharm专项训练5 最短路径算法
python·算法·pycharm
薄荷故人_1 小时前
从零开始的C++之旅——红黑树封装map_set
c++
qystca1 小时前
洛谷 P11242 碧树 C语言
数据结构·算法
冠位观测者1 小时前
【Leetcode 热题 100】124. 二叉树中的最大路径和
数据结构·算法·leetcode
悲伤小伞1 小时前
C++_数据结构_详解二叉搜索树
c语言·数据结构·c++·笔记·算法
m0_675988232 小时前
Leetcode3218. 切蛋糕的最小总开销 I
c++·算法·leetcode·职场和发展
佳心饼干-4 小时前
C语言-09内存管理
c语言·算法