质数判定,质因数分解,两种质数筛:埃氏筛、线性筛(欧拉筛)

news2024/11/15 12:18:42

质数判定

试除法,根据定义,枚举 [ 2 , n − 1 ] [2,n-1] [2,n1] 中所有整数,看是否有能整除 n n n 的数 。

事实上,我们没有必要枚举出所有整数

a × b = n a\times b=n a×b=n,我们就说 a a a b b b n n n 的因数,所以因数都是成对的,并且对称分布在 n \sqrt n n 两边,我们只需要找各对因数中较小的一个,而较小的因数一定小于等于 n \sqrt n n

bool isPrime(int n)
{
    if (n < 2) return false;
    for (int i = 2; i <= n / i; ++i)
    {
        if (n % i == 0) return false;
    }
    return true;
}

注意:判断条件 i <= n / i 是最优的写法。不建议写成 i <= sqrt(n),因为 sqrt() 求根号的速度比较慢。也不建议写成 i * i <= n 因为 i * i 容易导致 int 溢出。

时间复杂度: O ( n ) O(\sqrt n) O(n )

质因数分解

每个合数都可以写成几个质数相乘的形式,其中每个质数都是这个合数的因数,把一个合数用质因数相乘的形式表示出来,叫做分解质因数。如 30 = 2 × 3 × 5 30=2\times3\times5 30=2×3×5 10080 = 2 5 × 3 2 × 5 × 7 10080 = 2^5\times3^2\times5\times7 10080=25×32×5×7。分解质因数只针对合数。

求一个数分解质因数,要从最小的质数除起,一直除到结果为质数为止。分解质因数的算式叫短除法,和除法的性质相似,还可以用来求多个数的公因式。

短除法:

img

质因数分解代码:vector<pair<int, int>> 用于存放各质因数和对应的次数。

vector<pair<int, int>> divide(int x)
{
    vector<pair<int, int>> res;
    for (int i = 2; i <= x / i; ++i)
    {
        if (x % i == 0)
        {
            int s = 0;
            while (x % i == 0)
            {
                x /= i;
                ++s;
            }
            res.push_back({ i, s });
        }
    }
    if (x > 1) res.push_back({ x, 1 });
    return res;
}

这样写之所以正确,是基于一个基本原理:一个数除 1 1 1 以外的最小的因数一定是质数。

反证法很容易证明这一点:假设一个数 x x x 1 1 1 以外的最小的因数 y y y 不是质数,那么 y y y 有除 1 1 1 和它本身的因数 z z z z z z 一定也是 x x x 的因数,而 z < y z < y z<y,所以 y y y 不是 x x x 除1以外的最小的因数,与假设矛盾,原命题得证。

以上代码就是先找到这个数的第一个因数(以下所指的因数都不包括 1 1 1),它一定是质数,把它除干净之后得到一个新的数,新的数的最小的因数一定也是质数,而且比之前的大。最后如果 x x x 不能再分解,即 i i i 枚举到 x \sqrt x x 正好可以判断出 x x x 是个质数或者是 1,最后通过 x > 1 判断它也是一个质因数。

筛质数

找出 [ 1 , n ] [1,n] [1,n] 中所有的质数。

埃氏筛

[ 2 , n ] [2,n] [2,n] 全部列出来,依次划掉 2,3,4,5……n 的倍数。

对于任意一个 p 而言,如果它没有被划掉,那么说明它不是前面2~p-1的数的倍数,所以它一定是质数。

图解:

img

一开始可以确定 2 2 2 是质数,然后把 2 2 2 的倍数全部划掉; 3 3 3 没有被划掉,所以可以确定 3 3 3 是质数,然后把 3 3 3 的倍数全部划掉; 4 4 4 已经被 2 2 2 划掉了,它的倍数一定也是 2 2 2 的倍数,没必要再划了,跳过; 5 5 5 没有被划掉,可以确定 5 5 5 是质数,然后把 5 5 5 的倍数全部划掉……

4 4 4 这样的,合数的倍数不用再划,因为合数一定是前面某个数的倍数,那么它的倍数一定也是前面某个数的倍数。

这里还可以优化一个细节:比如我们在划 3 3 3 的倍数的时候,可以不从 3 × 2 = 6 3\times2=6 3×2=6 开始划,因为 6 6 6 已经被 2 2 2 划过了,而可以从 3 × 3 = 9 3\times3=9 3×3=9 开始划。同理,在划 5 5 5 的倍数的时候,应该从 5 × 5 = 25 5\times5=25 5×5=25 开始划,因为 5 × 2 5\times2 5×2 5 × 3 5\times3 5×3 5 × 4 5\times4 5×4 都被 2 2 2 3 3 3 划过了。

代码:

开两个数组,vector<int> primes用于存放质数,vector<bool> isPrime用于记录这些数是否被划掉,初始化所有数为 true,被划掉就标记成 false

void getPrimes(vector<int>& primes, vector<bool>& isPrime, int n)
{
    for (int i = 2; i <= n; ++i)
    {
        if (isPrime[i])
        {
            primes.push_back(i);
            for (long long j = (long long)i * i; j <= n; j += i)
            {
                isPrime[j] = false;
            }
        }
    }
}

防止 i * i 导致 int 溢出的写法:

void getPrimes(vector<int>& primes, vector<bool>& isPrime, int n)
{
    for (int i = 2; i <= n; ++i)
    {
        if (isPrime[i])
        {
            primes.push_back(i);
            for (int j = i; j <= n / i; ++j)
            {
                isPrime[j * i] = false;
            }
        }
    }
}

时间复杂度: O ( n log ⁡ log ⁡ n ) O(n\log\log n) O(nloglogn);这里的循环次数应该是 n 2 + n 3 + n 5 + ⋯ \frac{n}{2}+\frac{n}{3}+\frac{n}{5}+\cdots 2n+3n+5n+,把 n n n 提出来就是 n ( 1 2 + 1 3 + 1 5 + ⋯   ) n(\frac12+\frac13+\frac15+\cdots) n(21+31+51+),后面的一堆就是质数的倒数之和,它其实相当于 O ( log ⁡ log ⁡ n ) O(\log\log n) O(loglogn) ,所以总体的时间复杂度记为 O ( n log ⁡ log ⁡ n ) O(n\log\log n) O(nloglogn)

线性筛(欧拉筛)

为了提高效率,我们可以保证每个合数只被划掉一次,具体来说,是被它的最小质因数划掉。

我们知道,任何合数 x x x 都能分解质因数,因为合数的定义是不仅能被 1 1 1 和自己整除,还能被其它整数整除,这其它整数逐级分解最终还是质数。而且其质因数中,一定有小于等于 x \sqrt x x 的质因数,这是线性筛能筛掉所有合数的基本保证。

具体方法就是划掉所有 x 乘小于等于 x 的最小质因数的质数所得到的数 x = 2,3,4,5,6……,下面我们结合代码来看:

void getPrimes(vector<int>& primes, vector<bool>& isPrime, int n)
{
    for (int i = 2; i <= n; ++i)
    {
        if (isPrime[i])
            primes.push_back(i);
        for (auto p : primes)
        {
            if (p * i > n) break;
            isPrime[p * i] = false;
            if (i % p == 0) break;
        }
    }
}

第 11 行,枚举到 i % p == 0break,因为我们是从小到大枚举当前得到的质数,所以

  • i % p == 0 时,p 一定是 i 的最小质因数,同时 p 一定是 p * i 的最小质因数,划掉 p * i

  • i % p != 0 时,pi 的最小质因数还要小,所以 p 也一定是 p * i 的最小质因数,划掉 p * i

此两种状态都保证了,p * i 是被自己的最小质因数筛掉。

如果 i % p == 0 时不 break,而是继续向后枚举质数,那么 p 就不是 p * i 的最小质因数了,因为此时 p > i的最小质因数i的最小质因数 也是 p * i 的质因数。而 i的最小质因数 不能保证是 p * i 的最小质因数,因为它不是从最小的质数开始枚举的。

对于一个合数 x x x,假设 p p p 是它的最小质因数,当 i 枚举到 x / p x/p x/p 的时候, x x x 就被筛掉了,所以 x x x 永远比 i i i 快一步,如果 i i i 没被筛掉,可以确定 i i i 是质数。

时间复杂度: O ( n ) O(n) O(n)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/138340.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【区块链-智能合约工程师】第四篇:Truffle框架安装和介绍(Windows)

文章目录第一次尝试安装&#xff08;fail&#xff09;简单介绍安装配置truffle命令报错&#xff1a;truffle 不是内部或外部命令truffle命令报错&#xff1a;Cannot find module fs/promises第二次尝试安装&#xff08;fail&#xff09;安装和配置npm安装ganache-cli节点仿真器…

Java高手速成│实战:应用数据库和GUI开发产品销售管理软件(2)

实战项目&#xff1a;应用数据库和GUI开发产品销售管理软件&#xff08;2&#xff09; 01、项目分析 改进实战项目——应用数据库和GUI开发产品销售管理软件&#xff08;1&#xff09;的设计和操作&#xff0c;并增加新的功能&#xff1b;利用按钮和文本框实现对数据库编程的…

荣耀破壁2022:蜕变的解法、蓄势的护法、进击的打法

“世上只有一种英雄主义&#xff0c;那就是在认清生活的真相后依然热爱生活”&#xff0c; 罗曼罗兰在《米开朗琪罗传》中写道。人如此&#xff0c;企业亦如此。12月30日&#xff0c;荣耀在新年致辞中提到&#xff1a;“真正的勇敢是在认清真相后依然热爱。”刚过去的2022年&am…

zOffice新年新版本!多项实用功能上线

2022年发生了很多大事&#xff0c;你们在2022年做过最有意义的事情是什么呢&#xff1f;或许这一年我们有很多不足&#xff0c;或许我们依旧还需努力&#xff0c;但是我们都将继续寻找人生的新篇章&#xff0c;在2023年到来之际&#xff0c;联想Filez也祝大家新年快乐&#xff…

都2023年了,诸佬们肯定熟知RabbitMQ了吧

前言&#xff1a;大家好&#xff0c;我是小威&#xff0c;24届毕业生&#xff0c;曾经在某央企公司实习&#xff0c;目前入职某税务公司。本篇文章将记录和分享RabbitMQ相关的知识点。 本篇文章记录的基础知识&#xff0c;适合在学Java的小白&#xff0c;也适合复习中&#xff…

EXCEL的查找:如何按 行号+列号 进行查询, 可用indirect() + match() 或 index() + match()

0 首先用match()等取得行号&#xff0c;列号 如果想根据行号列号&#xff0c;精确查找&#xff0c;另外一个区域的数据&#xff0c;可以用如下方法 INDIRECT("Sheet2!r"&MATCH($C11,Sheet2!$A:$A,0)&"C"&MATCH(D$10,Sheet2!$1:$1,0),FALSE) …

ERR_UNSAFE_PORT浏览器安全问题导致无法访问的解决方案

前言 出发点是Java Agent内存马的自动分析与查杀&#xff0c;实际上其他内存马都可以通过这种方式查杀 本文主要的难点主要是以下三个&#xff0c;我会在文中逐个解答 1.如何dump出JVM中真正的当前的字节码 2.如何解决由于LAMBDA表达式导致非法字节码无法分析的问题 3.如何对…

短视频带货流程话术

现在短视频热度高涨&#xff0c;已经成为人们娱乐休闲的一种方式。短视频人流量大&#xff0c;已经衍生出了直播带货、橱窗链接带货等方式&#xff0c;也吸引了一批想要带货的用户。前言现在短视频热度高涨&#xff0c;已经成为人们娱乐休闲的一种方式。短视频人流量大&#xf…

JDBC(使用java语言操作数据库)

JDBC概念&#xff1a;使用Java语言操作关系型数据库的一套api&#xff08;可以用一套标准的jdbc操作所有类型的数据库&#xff0c;jdbc是接口&#xff0c;每一个数据库&#xff08;mysql、oracle、db2...&#xff09;都去实现jdbc的接口&#xff0c;每个数据库的实现类都不一样…

LeetCode:11. 盛最多水的容器

11. 盛最多水的容器1&#xff09;题目2&#xff09;思路3&#xff09;代码4&#xff09;结果1&#xff09;题目 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x …

2023年1月4日:fastadminApi接口开发项目时遇到的问题

SelectPage selectpage(官方文档&#xff1a;动态下拉(SelectPage) - FastAdmin框架文档 - FastAdmin开发文档) 常规用法 下面介绍一个基础的动态下拉列表示例&#xff0c;如下 <input id"c-name" data-rule"required" data-source"category/sel…

AVS3变换之IST和ISTS

IST&#xff08;Implicit Selected Transform&#xff09;是AVS3中新增的针对intra块的变换工具&#xff0c;IST对intra块提供了两种可分离的变换核&#xff0c;编码器根据RDO选择最优的变换核&#xff0c;但是对于选中的变换核不在码流中传输其索引&#xff0c;而是将其索引隐…

day34【代码随想录】贪心算法之跳跃游戏、跳跃游戏||、K次取反后最大化的数组和

文章目录前言一、跳跃游戏&#xff08;力扣55&#xff09;二、跳跃游戏 II&#xff08;力扣45&#xff09;三、K次取反后最大化的数组和&#xff08;力扣1005&#xff09;前言 1、跳跃游戏 2、跳跃游戏|| 3、K次取反后最大化的数组和 一、跳跃游戏&#xff08;力扣55&#xff…

火热的低代码到底是什么?

低代码风头正紧&#xff0c;也是最近一段时间跟云原生一起被热捧&#xff0c;不管你是做后端开发、还是前端设计、销售、售前&#xff0c;如果你没接触过低代码你都不好意思说自己在软件领域工作&#xff0c;这边文章从我的角度聊聊低代码是什么、以怎么样的方式开发、及低代码…

react笔记_05函数组件与类组件的区别之capture value特性

函数组件与类组件在写法没有好坏之分&#xff0c;性能差距也几乎可以忽略&#xff0c;而且 React 会长期支持这两种写法。 React的函数式组件和类组件之间的根本区别 在心智模型上。 函数式组件具有 capture value 特性。 capture value特性 Capture Value 从字面上可以理解…

【已解决】office提示你的许可证不是正版,你可能是盗版软件的受害者?

三步即可先看效果步骤1、下载工具2、找到 修复Office许可证明问题3、填入KMS主机&#xff0c;点击修复如何查看正在使用的 KMS 主机地址&#xff1f;先看效果 步骤 1、下载工具 工具下载&#xff1a;https://otp.landian.vip/zh-cn/ 2、找到 修复Office许可证明问题 3、填入…

PEM格式RSA密钥解析(一)

Base64转16进制格式 后缀是.PEM 的数字证书是 BASE64 编码的&#xff0c;以 ASCII 码来表示。常见的证书如下所示&#xff08;以 RSA1024 为例&#xff09;&#xff1a; 私钥&#xff1a; ----BEGIN RSA PRIVATE KEY----- MIICWwIBAAKBgHU4CF6yvqb5WBhwcYfvh/o3NpwcSJlcfj0nIZ…

下载神器IDM安装与使用(保姆级教程)

下载神器IDM安装与使用&#xff08;保姆级教程&#xff09; 文章目录下载神器IDM安装与使用&#xff08;保姆级教程&#xff09;前言一、下载地址二、IDM是什么&#xff1f;三、作用与特点四、安装步骤总结前言 众所周知&#xff0c;下载工具是大家电脑里必装的软件之一。 但大…

大数据时代,制造业人要知道,为什么有ERP还要上SRM系统

每个公司都是在一个供应链中&#xff0c;每个公司都有自己的上下游。如今&#xff0c;企业间的竞争已不再是单一企业的单打独斗&#xff0c;而是由价值链与价值链、供应链与供应链的较量。上游厂商&#xff08;供应商&#xff09;直接影响到公司的产品与服务的价格及竞争能力。…

零售企业全域数据打通最佳实践

在数字化转型的实战中&#xff0c;零售企业面临着巨大的挑战&#xff0c;过去三年线下流量锐减&#xff0c;甚至不少门店关停&#xff0c;不少零售企业布局线上&#xff0c;但是这个也给零售企业带来另外一个挑战&#xff1a;IT资源有限的情况下&#xff0c;线上&线下的流量…