0x31 质数

0x31 质数

定义:

若一个正整数无法被除了1和它自身之外的任何自然数整除,则称该数为质数(或素数),否则则称该正整数为合数。

在整个自然数集合中,质数的数量不多,分布比较稀疏,对于一个足够大的整数N,不超过 N N N的质数大约有 N / l n N N/lnN N/lnN个,即 l n N lnN lnN个数中大约有一个质数。

1.质数的判定

试除法

若一个正整数 N N N为合数,则存在一个能整除 N N N的整数 T T T,其中 2 ≤ T ≤ N 2\leq T \leq \sqrt{N} 2TN

我们只需扫描 2 ∼ N 2\sim \sqrt{N} 2N 之间所有的整数,依次检查它们能否整除 N N N,若都不能整除,则 N N N是质数,否则 N N N是合数。试除法的时间复杂度是 O ( N ) O(\sqrt{N}) O(N )。当然我们需要特判0和1这两个数,它们既不是质数也不是合数。

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

“试除法”作为最简单也最经典的确定性算法,是我们在算法竞赛中通常会使用的方法。有一些效率更高的随机性算法,例如“Miller-Robbin”等,有较小的概率把合数误判定为质数,但多次判定合起来错误概率趋近于0。

2.质数的筛选

给定一个整数N,求出 1 ∼ N 1\sim N 1N之间所有的质数,称为质数的筛选问题。

Eratosthenes筛法(埃式筛法)

Eratosthenes筛法基于这样的想法:任意整数 x x x的倍数 2 x 2x 2x 3 x 3x 3x,…都不是质数。

我们可以从2开始,由小到大扫描每个数 x x x,然后把它的倍数 2 x 2x 2x 3 x 3x 3x,…, ⌊ N / x ⌋ ∗ x \lfloor N/x \rfloor *x N/xx标记为合数。当扫描到一个数,若它未被标记,则说明它不能被 2 ∼ x − 1 2\sim x-1 2x1之间的任何数整除,该数就是质数。

Eratosthenes筛法如下:

在这里插入图片描述

我们发现,2和3都会把6标记为合数。实际上,小于 x 2 x^2 x2 x x x的倍数在扫描更小的数时就已经被标记过了。因此,我们可以对Eratosthenes筛法进行优化,对于每个数 x x x,我们只需要从 x 2 x^2 x2开始,把 x 2 x^2 x2 ( x + 1 ) ∗ x (x+1)*x (x+1)x ( x + 2 ) ∗ x (x+2)*x (x+2)x,…, ⌊ N / x ⌋ ∗ x \lfloor N/x \rfloor *x N/xx标记为合数即可。

void prime(int n)
{
    memset(v,0,sizeof(v)); //合数标记,全都标记为质数
    for(int i=2;i<=n;++i)
    {
        if(v[i]) 
            continue;
        cout<<i<<endl; //i是质数
        for(int j=i;j<=n/i;++j)
            v[i*j]=1;
	}
}

Eratosthenes筛法的时间复杂度为 O ( ∑ 质数 p ≤ N N P ) = O ( N l o g l o g n ) O(\sum_{质数p\leq N} \frac{N}{P})=O(Nloglogn) O(质数pNPN)=O(Nloglogn)。该算法实现简单,效率已经非常接近线性,是算法竞赛中最常用的质数筛法。

Euler筛法(欧拉筛法/线性筛法)

即使在优化后(从 x 2 x^2 x2开始),Eratosthenes筛法仍然会重复标记合数。例如12既会被2标记又会被3标记。其根本原因是我们没有确定出唯一的产生12的方式。

线性筛法通过“从小到大累计质因子”的方式标记每一个合数,即让12只有3*2*2一种方式产生。设数组 v v v记录每个数的最小质因子,我们按照以下步骤维护 v v v

1.依次考虑 2 ∼ N 2\sim N 2N中的每个数 i i i

2.若 v [ i ] = i v[i]=i v[i]=i,说明 i i i是质数,把它保存下来。

3.扫描不大于 v [ i ] v[i] v[i]的每个质数 p p p,令 v [ i ∗ p ] = p v[i*p]=p v[ip]=p。也就是在 i i i的基础上累积一个质因子 p p p。因为 p ≤ v [ i ] p\leq v[i] pv[i],所以 p p p就是合数 i ∗ p i*p ip的最小质因数。

在这里插入图片描述

每个合数只会被它的最小质因数 p p p筛一次,时间复杂度为 O ( n ) O(n) O(n)

int v[MAX_N],prime[MAX_N];
int m=0; //质数数量
void primes(int n)
{
    memset(v,0,sizeof(v)); //最小质因子
    for(int i=2;i<=n;++i)
    {
        if(v[i]==0)
            v[i]=i,prime[++m]=i;
        //给当前的i乘上一个质因子
        for(int j=1;j<=m;++j)
        {
            //i有比prime[j]更小的质因子或超出n的范围,停止循环
            if(prime[j]>v[i]||prime[j]*i>n)
                break;
            //prime[j]是合数prime[j]*i的最小质因子
           	v[prime[j]*i]=prime[j];
		}
	}
}

我们也可以直接把 v v v数组改为 i s _ p r i m e is\_prime is_prime数组,判断这个数是不是质数。

bool is_prime[MAX_N];
int prime[MAX_N];
int m;
void prime(int n)
{
    for(int i=2;i<=n;++i)
        is_prime[i]=true;
    for(int i=2;i<=n;++i)
    {
        if(is_prime[i])
            prime[++m]=i;
       	for(int j=1;j<=m&&i*prime[j]<=n;++j)
        {
            is_prime[i*prime[j]]=false;
            //如果i整除prime[j],则说明prime[j]正好是i*prime[j]最小质因数
            //后面的prime[j+1]大于最小质因数,退出循环
            if(i%prime[j]==0)
                break;
        }
	}
}

但是这个写法的实际运行时间可能与优化后的埃式筛法近似,因为存在低效的取模运算。

3.质因数分解

算术基本定理

任何一个大于1的正整数都能唯一分解为有限个质数的乘积,可写作:
N = p 1 c 1 p 2 c 2 . . . p m c m N=p_1^{c_1}p_2^{c_2}...p_m^{c_m} N=p1c1p2c2...pmcm
其中 c i c_i ci都是正整数, p i p_i pi都是质数,且满足 p 1 < p 2 < . . . < p m p_1<p_2<...<p_m p1<p2<...<pm

试除法

结合质数判定的“试除法”和质数筛选的“Eratosthenes筛法”,我们可以扫描 2 ∼ ⌊ N ⌋ 2\sim \lfloor \sqrt{N} \rfloor 2N 的每个数 d d d,若 d d d能整除 N N N,则从 N N N中除掉所有因子 d d d,同时累计除去的 d d d的个数。时间复杂度为 O ( N ) O(\sqrt{N}) O(N )

void divide(int n)
{
    m=0;
    for(int i=2;i<=sqrt(n);++i)
    {
        if(n%i==0)//i是质数
        {
            p[++m]=i,c[m]=0;
            while(n%i)
                n/=i,c[m]++;
        }
	}
    if(n>1) //n是质数
        p[++m]=n,c[m]=1;
}

Pollard's Rho”算法是一个比“试除法”效率更高的质因数分解方法。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

机器学习项目精选 第一期:超完整数据科学资料合集

大噶吼&#xff0c;不说废话&#xff0c;分享一波我最近看过并觉得非常硬核的资源&#xff0c;包括Python、机器学习、深度学习、大模型等等。 1、超完整数据科学资料合集 地址&#xff1a;https://github.com/krishnaik06/The-Grand-Complete-Data-Science-Materials Pytho…

strlen的三种模拟实现方法

首先&#xff0c;我们要了解strlen函数的参数以及返回值&#xff0c;还有使用方法。 1. 计数器方法 #include <stdio.h>size_t my_strlen(const char* str) {int count 0;while (*str) {count;}return count; } int main() {char arr[] "abcdef";int len …

专科论文降重修改技巧 神码ai

大家好&#xff0c;今天来聊聊专科论文降重修改技巧&#xff0c;希望能给大家提供一点参考。 以下是针对论文重复率高的情况&#xff0c;提供一些修改建议和技巧&#xff0c;可以借助此类工具&#xff1a; 专科论文降重修改技巧 在专科论文的撰写过程中&#xff0c;查重率是一…

高质量C/C++代码心得

写出高质量的C/C代码是一个涉及多方面的任务&#xff0c;它要求程序员不仅具备扎实的语言基础&#xff0c;还需要掌握一系列的软件设计和开发原则。下面将详细介绍如何写出高质量的C/C代码&#xff0c;并通过10个例子进行具体阐述。 一、编码规范 编写高质量的代码&#xff…

时序预测 | Python实现LSTM-Attention-XGBoost组合模型电力需求预测

时序预测 | Python实现LSTM-Attention-XGBoost组合模型电力需求预测 目录 时序预测 | Python实现LSTM-Attention-XGBoost组合模型电力需求预测预测效果基本描述程序设计参考资料预测效果 基本描述 该数据集因其每小时的用电量数据以及 TSO 对消耗和定价的相应预测而值得注意,从…

力扣刷题-二叉树-二叉树左叶子之和

404 左叶子之和 给定二叉树的根节点 root &#xff0c;返回所有左叶子之和。 示例 1&#xff1a; 输入: root [3,9,20,null,null,15,7] 输出: 24 解释: 在这个二叉树中&#xff0c;有两个左叶子&#xff0c;分别是 9 和 15&#xff0c;所以返回 24 思路 迭代法 迭代法理解…

springboot升级到3.2导致mybatis-plus启动报错

在springboot升级到3.2时&#xff0c;服务启动报错 java.lang.IllegalArgumentException: Invalid value type for attribute ‘factoryBeanObjectType’: java.lang.String&#xff1a; java.lang.IllegalArgumentException: Invalid value type for attribute factoryBeanOb…

基于Java SSM框架实现水果销售网站系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现水果销售网站系统演示 摘要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&a…

Linux 基本语句_16_Udp网络聊天室

代码&#xff1a; 服务端代码&#xff1a; #include <stdio.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdlib.h> #include <unistd.h> #include <string…

信号量机制理论详解专题

一文学懂信号量机制的各种大题&#xff0c;详细操作见下文~ 1965年&#xff0c;荷兰学者Dijkstra提出的信号量&#xff08;Semaphores&#xff09;机制是一种卓有成效的进程同步工具。在长期且广泛的应用中&#xff0c;信号量机制又得到了很大的发展&#xff0c;它从整型信号量…

LRU 缓存机制_题解(一道经典的数据结构算法题)

LRU 缓存机制_题解&#xff08;一道经典的数据结构算法题&#xff09; 146. LRU 缓存 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存 int get(int k…

spark介绍及简单使用

简介 Spark是由加州大学伯克利分校AMPLab&#xff08;AMP实验室&#xff09;开发的开源大数据处理框架。起初&#xff0c;Hadoop MapReduce是大数据处理的主流框架&#xff0c;但其存在一些限制&#xff0c;如不适合迭代算法、高延迟等。为了解决这些问题&#xff0c;Spark在20…

jmeter如何循环运行到csv文件最后一行后停止

1、首先在线程组中设置’循环次数‘–勾选永远 2、csv数据文件设置中设置&#xff1a; 遇到文件结束符再次循环?——改为&#xff1a;False 遇到文件结束符停止线程?——改为&#xff1a;True 3、再次运行就会根据文档的行数运行数据 &#xff08;如果需要在循环控制器中&…

Git----学习Git第一步基于 Windows 10 系统和 CentOS7 系统安装 Git

查看原文 文章目录 基于 Windows 10 系统安装 Git 客户端基于 CentOS7 系统安装部署 Git 基于 Windows 10 系统安装 Git 客户端 &#xff08;1&#xff09;打开 git官网 &#xff0c;点击【windows】 &#xff08;2&#xff09;根据自己的电脑选择安装&#xff0c;目前一般w…

【Unity自动寻路】使用Navigation系统实现物体自动寻路绕开障碍物

知识点流程图 自动导航Navigation系统 我们在游戏场景中经常会有一些障碍物、墙壁、树木等等&#xff0c;如果我想要让角色或者怪物去墙的另一边&#xff0c;我直接在墙另一边点击左键&#xff0c;我希望角色自动跑过去&#xff0c;但是他不能直接穿透墙&#xff0c;他需要“智…

java8新特性之-LocalDateTime

java8新特性之-LocalDateTime 首先&#xff0c;我们必须明确&#xff0c;JAVA为什么在有Date这个类的情况下&#xff0c;又引入了LocalDateTime 大体上来说。 java8引入为了解决旧的java.util.Date和java.util.Calendar等类在处理日期和时间时存在的一些问题&#xff0c;并提供…

[python]用python获取EXCEL文件内容并保存到DBC

目录 关键词平台说明背景所需库实现过程方法1.1.安装相关库2.代码实现 关键词 python、excel、DBC、openpyxl 平台说明 项目Valuepython版本3.6 背景 在搭建自动化测试平台的时候经常会提取DBC文件中的信息并保存为excel或者其他文件格式&#xff0c;用于自动化测试。本文…

一篇文章了解Flutter Json系列化和反序列化

目录 一. 使用dart:convert实现JSON格式编解码1. 生成数据模型类2. 将JSON数据转化成数据模型类3. 数据模型类转化成JSON字符串 二、借助json_serializable实现Json编解码1.添加json_annotation、build_runner、json_serializable依赖2. 创建一个数据模型类3. 使用命令行生成JS…

http状态码(一)400报错

一 400报错汇总 ① 综述 一、4xx状态码报错说明&#xff1a; 客户端行为导致的报错二、通用的4xxHTTP报错1) 4002) 4013) 4034) 4045) 405 --> 不允许方法&#xff0c;可能跨域或者nginx限制请求方法6) 4087) 4138) 419三、ngin自身定义的4xx报错495、496、497、498、4…

centOS7 安装tailscale并启用子网路由

1、在centOS7上安装Tailscale客户端 #安装命令所在官网位置&#xff1a;https://tailscale.com/download/linux #具体命令为&#xff1a; curl -fsSL https://tailscale.com/install.sh | sh #命令执行后如下图所示2、设置允许IP转发和IP伪装。 安装后&#xff0c;您可以启动…