• 【瞎口胡】基础数学 3 筛法


    写在前面

    还记得第一篇的内容吗?不记得了可以去复习一下。

    这一篇将会用到它们。

    Eratosthenes 筛法

    译名埃拉托色尼筛法。用于筛选 ([1,n]) 范围内的素数。

    其算法思想是,一个质数的所有倍数都不是质数。每当我们筛选到一个质数 (k) 时,我们就把 (xk (x>1 and xk leq n)) 标记为合数。

    bool vis[500010];
    int n;
    ...
    scanf("%d",&n);
    for(int i=2;i<=n;++i){
        if(!vis[i]){
            for(int j=1;i*j<=n;++j){
            	vis[i*j]=true;
    		}
    	}
    }
    // 注意 1 不是质数,因此不能简单地用 !vis[x] 来判断 x 是否为质数,应为 !vis[x]&&x!=1
    

    其时间复杂度为 (O(n log log n)),近似于线性。证明较为复杂,感兴趣的读者可以自行查阅。

    但我们仍然有严格 (O(n)) 的算法。

    线性筛法 / 欧拉筛法

    Eratosthenes 不够优秀的原因之一是一个合数可能被它的多个质因子筛掉。为此,我们引入线性筛法,对于每个合数,它只会被自己的最小质因子筛掉,因此是 (O(n))

    假设我们已经知道了 (leq i) 的正整数中,每个数是质数与否。令 (vis_i) 表示某个数是否被标记为质数((vis_i=1) 即为合数,反之则为质数),(operatorname{prime}_{1},operatorname{prime}_2,...,operatorname{prime}_s) 表示 (leq i) 的质数序列。不妨假设 (operatorname{prime}) 序列单调递增。

    对于这样的 (i),我们依次将 (vis_{i imes operatorname{prime}_j}(i imes operatorname{prime}_j leq n and 1 leq j leq s)) 标记为 (1)。如果在这个过程中发现存在某个 (j) 使得 (operatorname{prime}_j mid i),则不再进行后续的标记。

    这样做的正确性是有保证的。假设出现 (operatorname{prime}_j mid i) 时有 (j=v),那么有:

    1. 所有 (j leq v)(注意不是 (<))都满足 (operatorname{prime}_j)(i imes operatorname{prime}_j) 的最小质因子。
  • 相关阅读:
    MQTT 连接服务端失败,报错客户机未连接(32104)
    引入其他类定义的静态变量
    Linux 中文乱码问题
    MQTT 简介
    mybatis xml 特殊字符转义
    如何科学的高效率的选择创建线程数
    【安卓自定义控件系列】自绘控件打造界面超炫功能超强的圆形进度条
    Eclipse简介和使用技巧快捷方式
    MyEclipse如何全局搜索
    JAVA面向对象-----访问修饰符
  • 原文地址:https://www.cnblogs.com/liuzongxin/p/14864268.html
Copyright © 2020-2023  润新知