【数论】质数

news2025/7/29 6:03:06

文章目录

    • 一、试除法判定质数
    • 二、试除法分解质因数
    • 三、筛法求素数
      • 1. 朴素筛法
      • 2. 埃氏筛法
      • 3. 线性筛法

质数:大于1,且只包含1和本身两个因数的整数

一、试除法判定质数

如果是合数,那么因数一定是成对出现的,比如12,有2*6=12,3*4=12,我们不用暴力枚举,从2一直枚举到n-1,我们只枚举成对出现的因数中较小的即可

比如当前数为n,有因数c和因数n/c,我们希望 c < = n c c<=\frac{n}{c} c<=cn,并从2枚举到c,那c的范围就是 c < = n c<=\sqrt{n} c<=n

bool isPrime(int n) {
	if (n < 2) {
		return false;
	}
	// 判断条件为i <= sqrt(n),sqrt计算较慢,不推荐
	// 判断条件为i * i <= n,当n很接近INT_MAX时,i*i可能会大于INT_MAX,这就移除了,i*i变成负数,负数永远小于n,影响判断,不推荐
	for (int i = 2; i <= n / i; i++) {
		if (n % i == 0) {
			return false;
		}
	}
	return true;
}

时间复杂度一定是 O ( n ) O(\sqrt{n}) O(n )

二、试除法分解质因数

void divide(int n) {
	// 条件为i <= n,是暴力枚举n的因子
	for (int i = 2; i <= n / i; i++) {
		// 我们这里的i是否可能是合数呢?不可能
		if (n % i == 0) {
			// 我们枚举到i时,n中就不再包含2~i-1中的任何质因子了,且n % i == 0,因此i也不再有2~i-1中的任何质因子,所以i一定是质数
			int num = 0;
			while (n % i == 0) {
				n /= i;
				num++;
			}
			cout << i << " " << num << endl;
		}
	}
	// 数n最多只存在一个大于sqrt(n)的质因子,除开所有质因子后,若值依然大于1,则此时的n就是最大的质因子
	if (n > 1) {
		cout << n << " " << 1 << endl;
	}
}

时间复杂度最差是 O ( n ) O(\sqrt{n}) O(n ),最好是 l o g 2 n log_2n log2n,这里的数n是不断除自己的因子,可以降低时间复杂度

三、筛法求素数

1. 朴素筛法

使用2~n之间的数进行剔除
在这里插入图片描述

如果某个数p没有被删除,就意味着我们使用2~p-1没有把p删除,则p一定是质数

// 求1~n中素数的数量
int getPrimes(int n) {
	// 表示数组中的数是否被删除
	vector<bool> isDeleted(n + 1, false);
	int cnt = 0;
	for (int i = 2; i <= n; i++) {
		if (!isDeleted[i]) {
			cnt++;
		}
		// 删除i的倍数
		for (int j = i + i; j <= n; j += i) {
			isDeleted[j] = true;
		}
	}
	return cnt;
}

当i=2时,内层循环执行 n / 2 n/2 n/2,当i=3时,内层循环执行 n / 3 n/3 n/3,…,当i=n时,内层循环执行 n / n n/n n/n,时间复杂度为 n 2 + n 3 + . . . + n n \frac{n}{2}+\frac{n}{3}+...+\frac{n}{n} 2n+3n+...+nn,调和级数,当n趋近于正无穷时,极限是 n ( ln ⁡ n + 0.577 ) n(\ln n+0.577) n(lnn+0.577),时间复杂度接近于 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)

2. 埃氏筛法

埃氏筛法改进: 素数的倍数一定不是素数,在用素数剔除时,一定会剔除合数。没必要再用合数剔除,只用素数剔除

由算术基本定理,只需要使用2~n-1中的素数进行剔除即可

// 求1~n中素数的数量
int getPrimes(int n) {
	// 表示数组中的数是否被剔除
	vector<bool> isDeleted(n + 1, false);
	int cnt = 0;
	for (int i = 2; i <= n; i++) {
		if (!isDeleted[i]) {
			cnt++;
			// 删除素数i的倍数
			for (int j = i + i; j <= n; j += i) {
				isDeleted[j] = true;
			}
		}
	}
	return cnt;
}

时间复杂度为 n 2 + n 3 + . . . + n n \frac{n}{2}+\frac{n}{3}+...+\frac{n}{n} 2n+3n+...+nn,其中分母只有素数,根据素数定理,1~n中大概有 n ln ⁡ n \frac{n}{\ln n} lnnn个素数,时间复杂度大概是朴素解法的 ln ⁡ n n \frac{\ln n}{n} nlnn倍,即 ( ln ⁡ n ) 2 (\ln n)^2 (lnn)2,真实的时间复杂度大概是 O ( n l o g l o g n ) O(nloglogn) O(nloglogn),基本上就是 O ( n ) O(n) O(n)

3. 线性筛法

算法核心:一个数n只会被最小的质因子筛掉

int getPrimes(int n) {
	vector<int> primes;                    // 记录素数
	vector<bool> isDeleted(n + 1, false);  // 表示数组中的数是否被删除
	int cnt = 0;
	for (int i = 2; i <= n; i++) {
		if (!isDeleted[i]) {
			primes.push_back(i);           // 没有被筛掉,则记录素数
			cnt++;
		}
		// 开始枚举n的质因子
		int up = n / i;
		for (int j = 0; primes[j] <= up; j++) {
			isDeleted[primes[j] * i] = true; // primes[j]一定是i的最小质因子
			if (i % primes[j] == 0) break;
		}
	}
	return cnt;
}

i % primes[j] != 0时,说明此时遍历到的primes[j]不是i的质因子,且因为当前的i是素数表里最大的素数,则primes[j] < i,所以primes[j] * i的最小质因子就是primes[j]

当有i % primes[j] == 0时,说明i的最小质因子是primes[j],因此primes[j] * i的最小质因子也就应该是prime[j],之后接着用isDeleted[primes[j+1] * i] = true去筛合数时,就不是用最小质因子去更新了,因为i有最小质因子primes[j] < primes[j+1],此时的primes[j+1]不是primes[j+1] * i的最小质因子,此时就应该退出循环,避免之后重复进行筛选

在这里插入图片描述
图中的X都是primes[j]等于对应数的最小质因子是被筛掉的

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

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

相关文章

【Axure教程】能增删改数据的动态饼图

可视化视图是系统分析中非常重要的一个环节&#xff0c;今天作者就教大家在Axure中如何用中继器表格结合echarts图片&#xff0c;制作出一个能够动态增删改数据饼图的原型模板。需要制作的效果如下图所示&#xff1a; 自动生成饼图&#xff1a;通过修改中继器表格中的数据&…

教程三 在Go中使用Energy创建跨平台应用 - 状态控制

本文介绍在Energy中如何像浏览器一样控制状态, 页面的加载、前进、后退、刷新、暂停刷新 前提-需要安装好开发环境参考:教程一环境安装 创建应用 开发环境中 MacOSX平台必须在"GlobalCEFInit"之前设置CEF设置使用CEF 和 CEF框架目录&#xff0c;生成开发执行应用程…

【kafka】十、kafka消费者offset维护

消费者offset维护 offset维护 由于consumer在消费过程中可能会出现断电宕机等故障&#xff0c;consumer恢复后&#xff0c;需要从故障前的位置继续消费&#xff0c;所以consumer需要实时记录自己消费到了哪个offset&#xff0c;以便恢复后继续消费。 消费者是按照消费者组来保…

第八章 动态规划 3 AcWing 1554. 找更多硬币

第八章 动态规划 3 AcWing 1554. 找更多硬币 原题链接 AcWing 1554. 找更多硬币 算法标签 DP 背包问题 思路 经典01背包问题 闫氏DP分析法 状态表示 状态初始化 状态计算 状态转移方程式 要求字典序最小&#xff0c;因此先存硬币面额到数组再降序排列&#xff0c;保…

App逆向之frida-dexdump脱壳分析某肿瘤sign

声明&#xff1a;本文仅限学习交流使用&#xff0c;禁止用于非法用途、商业活动等。否则后果自负。如有侵权&#xff0c;请告知删除&#xff0c;谢谢&#xff01;本教程也没有专门针对某个网站而编写&#xff0c;单纯的技术研究 一、firda 的安装 国内下载很慢&#xff1a;pip…

docker容器网络

第七章容器网络 Docker网络 veth pair&#xff1a;成对出现的一种虚拟网络设备&#xff0c;数据从一端进&#xff0c;从另一端出。用于解决网络命名空间之间隔离。 docker0&#xff1a;网桥是一个二层网络设备&#xff0c;通过网桥可以将Linux支持的不同端口连接起来&…

Git常见命令与使用,从0到1学会使用Git

&#x1f468;‍&#x1f4bb;个人主页&#xff1a; 才疏学浅的木子 &#x1f647;‍♂️ 本人也在学习阶段如若发现问题&#xff0c;请告知非常感谢 &#x1f647;‍♂️ &#x1f4d2; 本文来自专栏&#xff1a; 常见软件安装与运用 ❤️ 支持我&#xff1a;&#x1f44d;点赞…

linux NPS 服务端安装 +linux 客户端安装

本文参考博客&#xff1a; https://blog.csdn.net/m0_57776598/article/details/123674866 一、下载安装包 1、官方下载 官方下载地址&#xff1a;https://github.com/ehang-io/nps/releases 注意不要下错了&#xff0c;当前我下的版本为 v0.26.10 2、网盘下载 网盘下载&…

Python编程 字典的常用操作

作者简介&#xff1a;一名在校计算机学生、每天分享Python的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.字典 1.访问字典(掌握) 2.字典的增加与修改(掌握) 3.系列删除(掌握) …

Web3中文|元宇宙在商业中的最佳应用

来源 | techrepublic 编译 | DaliiNFTnews.com 麻省理工学院斯隆管理学院的信息技术高级讲师Paul McDonagh-Smith说&#xff0c;麻省理工学院的人工智能先驱Marvin Minsky创造了“手提箱式词语”一词——即一些词或术语本身没有任何意义&#xff0c;而需要人去挖掘、赋予和丰…

计算机英文论文写作需要注意哪些细节? - 易智编译EaseEditing

1&#xff09;尽量用动词少用名词化 那些大篇名词的文章真的很难读懂&#xff0c;而有强大动词的句子更容易理解。 我们注意到客户在论文中经常使用的名词有“agreement”, “disagreement”, “investigation”, “analysis”, “examination”, “comparison”, “increase…

【MySQL技术专题】「索引技术」体验前所未有的技术探险,看穿索引的本质和技术体系(1)

文章目录前提概要数据库类型内容架构索引和磁盘的关系数据读取时主要时间开销总结分析瓶颈点优化的方式数据量计算传统暴力&#xff08;顺序型读写&#xff09;X索引机制&#xff08;半随机性读写&#xff09;√索引升级之多级索引化&#xff08;全随机性读写&#xff09;使用索…

读书笔记《Spring Boot+Vue全栈开发实战》(下)

本书将带你全面了解Spring Boot基础与实践&#xff0c;带领读者一步步进入 Spring Boot 的世界。前言第九章 Spring Boot缓存第十章 Spring Boot安全管理第十一章 Spring Boot整合WebSocket第十二章 消息服务第十三章 企业开发第十四章 应用监控第十五章 项目构建与部署第十六章…

【python与数据分析】Pandas统计分析基础

目录 前言 一、pandas常用数据类型 综述 1.一维数组&#xff08;Series&#xff09;与常用操作 &#xff08;1&#xff09; 通过列表创建Series &#xff08;2&#xff09;创建Series时指定索引 &#xff08;3&#xff09;Series位置和标签的使用 &#xff08;4&#x…

m基于中继协助的认知无线电频谱切换机制的matlab仿真分析

目录 1.算法描述 2.仿真效果预览 3.MATLAB部分代码预览 4.完整MATLAB程序 1.算法描述 认知无线电网络在进行频谱切换的时候&#xff0c;最为重要的问题是如何以最少的频谱切换次数实现频谱切换&#xff0c;同时保证较好的服务质量&#xff0c;这里&#xff0c;服务质量不仅…

植入“人工心脏”助患者重获“心”生

【同期】人工心脏移植患者 刘女士这要是在过去的时候也就放弃了&#xff0c;我再活20年&#xff0c;我还能看着我大孙子成家&#xff0c;这就是我最大的希望。【解说】11月22日&#xff0c;人工心脏移植患者和心脏移植患者在即将康复出院前&#xff0c;互相握手庆贺。据了解&am…

【UDS】ISO14229之0x3E服务

文章目录前言一、理论描述二、使用步骤1.请求2.响应总结->返回总目录<- 前言 简称&#xff1a; “TesterPresent”&#xff0c;测试工具保持连接服务 功能&#xff1a; 此服务用于告知电控单元测试工具仍在线。该服务需周期性发送&#xff0c;用于重置 S3server 计时器…

SQL语句练习

1. 创建学生表 S(命名格式“姓名拼音_三位学号_s”&#xff0c;如 LBJ_023_s)并插入数据 2. 创建课程表 C(命名格式“姓名拼音_三位学号_c”&#xff0c;如 LBJ_023_c) 并插入数据 3. 创建选课表 SC(命名格式“姓名拼音_三位学号_sc”&#xff0c;如 LBJ_023_sc) 并插入数据 …

寻找链表相交结点问题

寻找链表相交结点问题 作者&#xff1a;Grey 原文地址&#xff1a; 博客园&#xff1a;寻找链表相交结点问题 CSDN&#xff1a;寻找链表相交结点问题 题目描述 给定两个可能有环也可能无环的单链表&#xff0c;头节点head1和head2。请实现一个函数&#xff0c;如果两个链表…

Vue3路由守卫、vuex的使用、vuex模块化拆分、vite中自动导入模块文件

文章目录1. 路由守卫2. vuex的使用2.1 基本使用2.2 模块化拆分方式一方式二方式三3. 在vite中自动导入模块文件1. 路由守卫 vue3 中的导航守卫与 vue2 中的基本一致&#xff0c;不同的地方在于&#xff0c;vue3 中导航守卫取消了 next 参数&#xff0c;而是通过返回 false 来取…