数论——质数和合数及求质数

质数、合数和质数筛

  • 质数和合数及求质数
    • 试除法判断质数
    • Eratosthenes筛选法(埃氏筛)
    • 线性筛(欧拉筛)
  • 质数有关OJ列举
    • P1835 素数密度 - 洛谷
    • 简单的哥赫巴德猜想和cin优化

质数和合数及求质数

一个大于 1 的自然数,除了 1 和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数。其中,质数又称素数。有的资料用的词不同,但质数和素数其实是一回事。

规定 1 既不是质数也不是合数。

试除法判断质数

  • 对于一个数 x x x,根据定义,可以从 [ 2 , x − 1 ] [2, x - 1] [2,x1] 一个一个尝试,判断 x x x 能否被整除。

但是,没有必要每一个都去判断。因为 a a a 如果是 x x x 的约数,那么 x / a x / a x/a 也是 x x x 的约数。因此,我们仅需判断较小的 a a a 是否是 x x x 的约数,没有必要再去看看 x / a x / a x/a。那么,仅需枚举到 x \sqrt{x} x 即可。

试除法实现:

bool prim(int x) {if (x < 2)return false;for (int i = 2; i <= x / i; i++)//i*i<=x,所以i<=x/i,这是防溢出写法if (x % i == 0)return false;return true;
}

时间复杂度:因为是枚举到 n \sqrt{n} n ,所以时间复杂度为 O ( N ) O(\sqrt{N}) O(N )

模板题:

P5736 【深基7.例2】质数筛 - 洛谷

#include<bits/stdc++.h>
using namespace std;bool prim(int x) {if (x < 2)return false;for (int i = 2; i <= x / i; i++)if (x % i == 0)return false;return true;
}int main() {int n; cin >> n;for (int x = 0; n--;) {cin >> x;if (prim(x))cout << x << ' ';}return 0;
}

Eratosthenes筛选法(埃氏筛)

模板题:P3383 【模板】线性筛素数 - 洛谷

在很多场景我们需要知道[2, n]内有多少个质数,或正数、倒数第 k k k个质数是多少。 n n n 很有可能特别大,此时传统的试除法一个一个判断显然会很慢甚至无法在规定时间内完成判断。因此需要使用其他算法来筛选出指定范围内的质数。

Eratosthenes筛选法基本思想:质数的倍数一定不是质数。

实现方法:用一个长度为 N + 1 N+1 N+1 的数组vis保存信息(0 表示质数,1 表示非质数),先假设所有的数都是质数(初始化为 0),从小到大枚举每一个质数 x x x,把 x x x 的倍数都标记为非质数(置为 1)。当从小到大扫描时扫描到一个数 x x x ,若它尚未被标记,则它不能被 2 ∼ x − 1 2 \sim x-1 2x1 之间的任何数整除,该数就是质数。

整数 1 特殊处理即可。在筛数的时候可以从 x 2 x^2 x2开始筛,因为小于 x x x的合数是被筛选过的。

//Eratosthenes筛(埃氏筛)
void get_prim(vector<int>&vis, vector<int>&ans) {for (size_t i = 2; i < vis.size(); i++) {if (vis[i])continue;//记录素数ans.push_back(i);//从i*i开始,因为小于i的合数已经被筛掉了for (size_t j = i * i; j < vis.size(); j+=i)vis[j] = true;//筛掉合数}
}

时间复杂度(推荐直接记结论): O ( n log ⁡ log ⁡ n ) O(n\log\log n) O(nloglogn)。这里 n n n实际就是vis.size()

严谨的数学推导:埃氏筛法的时间复杂度的详细证明-CSDN博客

P3383 【模板】线性筛素数 - 洛谷参考程序(埃氏筛):

#include<bits/stdc++.h>
using namespace std;void Eratosthenes(vector<bool>& vis, vector<int>& ans) {for (size_t i = 2; i < vis.size(); i++) {if (vis[i])continue;ans.push_back(i);for (size_t j = i * i; j < vis.size(); j += i)vis[j] = true;}
}int main() {int n, q,num;scanf("%d %d", &n, &q);vector<bool>vis(n + 1, false);vector<int>ans;Eratosthenes(vis, ans);//埃氏筛while (q--) {scanf("%d", &num);cout << ans[num - 1] << endl;}return 0;
}

线性筛(欧拉筛)

线性筛法,又称欧拉筛法。在埃氏筛法中,它会将一个合数重复多次标记。如果能让每个合数都只被标记一次,那么时间复杂度就可以降到 O ( n ) O(n) O(n)

我们的做法是,让每一个合数被它的最小质因数筛掉

void get_prim(vector<int>& vis, vector<int>& ans) {for (size_t i = 2; i < vis.size(); i++) {if (!vis[i])//被标记为true时是合数ans.push_back(i);//1uLL是为了让size_t强制转换成unsigned long long防止溢出for (size_t j = 0; 1uLL * i * ans[j] < vis.size(); j++) {//筛掉合数vis[i * ans[j]] = true;//i是质数的倍数时停止,当i正好为最后一个质数时循环终止if (i % ans[j] == 0)break;}}
}

i%ans[j]==0这个判定条件能让每一个合数被自己的最小质因数筛掉。

  1. 如果 i 是合数,枚举到最小质因数的时候跳出循环
  2. 如果 i 是质数,枚举到自身时跳出循环
    注意,在筛的过程中,我们还能知道 p[j]i 的最小质因数

这个算法最多遍历2遍数组,也就是说实际的时间复杂度是 O ( 2 n ) O(2n) O(2n)

很多和数学有关的算法都是在欧拉筛的基础上实现(例如积性函数),因此欧拉筛很重要,需要理解这个算法的本质。

P3383 【模板】线性筛素数 - 洛谷参考程序(欧拉筛):

#include<bits/stdc++.h>
using namespace std;void Euler(vector<bool>& vis, vector<int>& ans) {for (size_t i = 2; i < vis.size(); i++) {if (!vis[i])ans.push_back(i);for (size_t j = 0; 1uLL * i * ans[j] < vis.size(); j++) {vis[i * ans[j]] = true;if (i % ans[j] == 0)break;}}
}int main() {int n, q,num;scanf("%d %d", &n, &q);vector<bool>vis(n + 1, false);vector<int>ans;Euler(vis, ans);//欧拉筛while (q--) {scanf("%d", &num);cout << ans[num - 1] << endl;}return 0;
}

质数有关OJ列举

P1835 素数密度 - 洛谷

P1835 素数密度 - 洛谷

因为 1 ≤ L ≤ R ≤ 2 31 1\leq L\leq R\leq 2^{31} 1LR231,无论是埃氏筛还是线性筛,在空间上会超限,在时间上遍历 2 31 2^{31} 231 O ( n ) O(n) O(n)的算法也无法在1秒内完成。

根据试除法,求一个数 r r r是否是质数,只需枚举 [ 1 , r ] [1, \sqrt{r}] [1,r ]

所以代码思路:

  • 先找出 [ 1 , R ] [1, \sqrt{R}] [1,R ]内的质数,再利用这些质数将 [ L , R ] [L,R] [L,R]内的合数标记。 R \sqrt{R} R 的数据范围是 [ 2 , 2 16 ] [2,2^{16}] [2,216] 2 16 = 65536 2^{16}=65536 216=65536,在可接受范围内,用埃氏筛或欧拉筛都可以。
  • 找到这些质数在 [ L , R ] [L,R] [L,R]内的最小合数后,用埃氏筛的做法标记 [ L , R ] [L,R] [L,R]内的其他合数。首先需要找到质数在 [ L , R ] [L,R] [L,R]的最小倍数。
    所以整体思路是埃氏筛 + 欧拉筛。

找质数在 [ L , R ] [L,R] [L,R]内的最小倍数:假设 p ∈ [ 1 , R ] p\in [1,\sqrt{R}] p[1,R ] p p p是质数,则 k p ≥ L kp\geq L kpL k ≥ ⌈ L p ⌉ k\geq \lceil\frac{L}{p}\rceil kpL,也就是说可以通过左端点除以质数并向上取整,再乘质数,即可得到最小倍数。即 ⌈ L p ⌉ × p \lceil\frac{L}{p}\rceil\times p pL×p

在计算机中求 ⌈ L p ⌉ \lceil\frac{L}{p}\rceil pL,特别是c++默认整数除法/会去除小数部分,所以可以通过对 L + ( p − 1 ) p \frac{L+(p-1)}{p} pL+(p1)向下取整来间接求得 ⌈ L p ⌉ \lceil\frac{L}{p}\rceil pL

  • L L L p p p的倍数,后面的 p − 1 p-1 p1对整体不构成影响;
  • 若不是,则在浮点数的视角, L p \frac{L}{p} pL会残留有小数部分,这一部分加上 p − 1 p \frac{p-1}{p} pp1大于1,所以通过 ⌊ L + ( p − 1 ) p ⌋ \lfloor\frac{L+(p-1)}{p}\rfloor pL+(p1)也能间接求得 ⌈ L p ⌉ \lceil\frac{L}{p}\rceil pL

综上, ⌊ L + ( p − 1 ) p ⌋ = ⌈ L p ⌉ \lfloor\frac{L+(p-1)}{p}\rfloor=\lceil\frac{L}{p}\rceil pL+(p1)=pL。在代码中可通过(L+p-1)/p*p得到质数 p p p的不小于 L L L的最小倍数。

其中需要注意的细节:

  1. L = 1 L=1 L=1,但1不是质数,所以此时需要从 L = 2 L=2 L=2开始。
  2. L ∈ [ 1 , R ] L\in [1,\sqrt{R}] L[1,R ] L L L可能是质数。
    例如{2,3,5},要求筛掉[5,25]中的合数, ⌊ 5 + 5 − 1 5 ⌋ × 5 = 5 \lfloor\frac{5+5-1}{5}\rfloor\times 5=5 55+51×5=5,因此会把5筛掉,但5是质数不能被筛掉,因为之前较小的质数已经把部分合数给晒掉了,所以若枚举到质数 p p p,则从 2 p 2p 2p开始筛,因此在使用埃氏筛的方法筛掉合数时可以从 max ⁡ ( 2 p , ⌊ L + ( p − 1 ) p ⌋ ) \max(2p,\lfloor\frac{L+(p-1)}{p}\rfloor) max(2p,pL+(p1)⌋)开始。
  3. 因为 R R R是有可能到 2 31 2^{31} 231,数组不可能开这么大,但可以通过小区间[0,R-L]来存储[L,R]的结果,再开一个 10 6 10^6 106的数组勉强能接受。
  4. 因为数据量整体过大,只有放弃vector转用一般的数组才能不超时。
#include<bits/stdc++.h>
using namespace std;typedef long long LL;
const int N = 1e6 + 10;
bool vis1[N], vis2[N];//因为超时,不得不换成普通数组
int ans[N], pans;
int L, R;void get_prim() {size_t n = sqrt(R);for (size_t i = 2; i <= n; i++) {if (!vis1[i])ans[++pans]=i;for (size_t j = 1; 1ull * i * ans[j] <= n; j++) {vis1[i * ans[j]] = 1;if (i % ans[j] == 0)break;}}
}int main() {cin >> L >> R;get_prim();L = L == 1 ? 2 : L;for (int i = 1; i <= pans;i++) {int x = ans[i];for (LL i = max(x * 2, (L + x - 1) / x * x);i<=R; i+=x) {vis2[i - L] = 1;}}int cnt = 0;for (int i = L; i <= R; i++) if (!vis2[i - L])++cnt;cout << cnt;return 0;
}

简单的哥赫巴德猜想和cin优化

UVA543 Goldbach’s Conjecture - 洛谷

1622:Goldbach’s Conjecture

这题是UVA上的题,但可以在信奥网站提交。

素数筛制表,然后查表即可。因为这个猜想至今仍然没有找到一个反例,所以直接找即可。

因为数据量过大,用cin输入时需要使用优化手段,或直接用scanf。而且不能用endl

#include<bits/stdc++.h>
using namespace std;const int N = 1e6 + 1;
bool vis[N];
int ans[N], pans;void get_prim() {for (int i = 2; i < N; i++) {if (!vis[i])ans[++pans] = i;for (int j = 1; 1ull*i * ans[j] < N; j++) {vis[i * ans[j]] = 1;if (i % ans[j] == 0)break;}}
}int main() {ios::sync_with_stdio(0);cin.tie(0);//不用这个对cin进行优化会超时//cout.tie(0);//这个有没有都不影响get_prim();int n;while (cin>>n, n) {for (int i = 1; i <= pans &&ans[i]<n; i++) {if (!vis[n - ans[i]]) {cout << n << " = " << ans[i] << " + " << n - ans[i] << "\n";break;}}}return 0;
}

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

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

相关文章

多商户系统源码性能调优实战:从瓶颈定位到高并发架构设计!

在电商业务爆发式增长的今天&#xff0c;多商户系统作为支撑平台方、入驻商家和终端消费者的核心枢纽&#xff0c;其性能表现直接决定了商业变现效率。当你的商城在促销期间崩溃&#xff0c;损失的不仅是订单&#xff0c;更是用户信任。 本文将深入剖析多商户系统源码性能优化的…

JDBC连不上mysql:Unable to load authentication plugin ‘caching_sha2_password‘.

最近为一个spring-boot项目下了mysql-9.3.0&#xff0c;结果因为mysql版本太新一直报错连不上。 错误如下&#xff1a; 2025-06-01 16:19:43.516 ERROR 22088 --- [http-nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispat…

超标量处理器设计6-指令解码

1. 指令缓存 指令缓存本质上是一个FIFO, 它能够将指令按照程序中指定的顺序存储起来&#xff0c;这样指令在解码的时候&#xff0c;仍然可以按照程序中指定的顺序进行解码。指令缓存是超标量处理器中必须的部件&#xff0c;其原因有两个&#xff1a; 1. 每周期可以取指的个数大…

基于 HT for Web 轻量化 3D 数字孪生数据中心解决方案

一、技术架构&#xff1a;HT for Web 的核心能力 图扑软件自主研发的 HT for Web 是基于 HTML5 的 2D/3D 可视化引擎&#xff0c;核心技术特性包括&#xff1a; 跨平台渲染&#xff1a;采用 WebGL 技术&#xff0c;支持 PC、移动端浏览器直接访问&#xff0c;兼容主流操作系统…

【Linux】shell的条件判断

目录 一.使用逻辑运算符判定命令执行结果 二.条件判断方法 三.判断表达式 3.1文件判断表达式 3.2字符串测试表达式 3.3整数测试表达式 3.4逻辑操作符 一.使用逻辑运算符判定命令执行结果 && 在命令执行后如果没有任何报错时会执行符号后面的动作|| 在命令执行后…

【Python办公】Excel简易透视办公小工具

目录 专栏导读1. 背景介绍2. 功能介绍3. 库的安装4. 界面展示5. 使用方法6. 实际应用场景7. 优化方向完整代码总结专栏导读 🌸 欢迎来到Python办公自动化专栏—Python处理办公问题,解放您的双手 🏳️‍🌈 博客主页:请点击——> 一晌小贪欢的博客主页求关注 👍 该系…

HarmonyOS鸿蒙与React Native的融合开发模式以及能否增加对性能优化的具体案例

鸿蒙与React Native的融合开发模式 一、技术架构设计 底层适配层 通过HarmonyOS的NDK封装原生能力&#xff08;如分布式软总线、AI引擎&#xff09; 使用React Native的Native Modules桥接鸿蒙API&#xff08;需重写Java/Objective-C部分为ArkTS&#xff09; 组件映射机制 …

LLaMA-Factory - 批量推理(inference)的脚本

scripts/vllm_infer.py 是 LLaMA-Factory 团队用于批量推理&#xff08;inference&#xff09;的脚本&#xff0c;基于 vLLM 引擎&#xff0c;支持高效的并行推理。它可以对一个数据集批量生成模型输出&#xff0c;并保存为 JSONL 文件&#xff0c;适合大规模评测和自动化测试。…

麦克风和电脑内播放声音实时识别转文字软件FunASR整合包V5下载

我基于FunASR制作的实时语音识别转文字软件当前更新到V5版本。软件可以实时识别麦克风声音和电脑内播放声音转为文字。 FunASR软件介绍 FunASR 是一款基础语音识别工具包和开源 SOTA 预训练模型&#xff0c;支持语音识别、语音活动检测、文本后处理等。 我使用FunASR制作了一…

子串题解——和为 K 的子数组【LeetCode】

谨记&#xff1a; 数组不是单调的话&#xff0c;不要用滑动窗口&#xff0c;考虑用前缀和 写法一&#xff1a;两次遍历 代码的核心思想是通过 前缀和 和 哈希表 来高效地统计符合条件的子数组个数。具体步骤如下&#xff1a; 计算前缀和数组 s&#xff1a; s[i] 表示 nums 的前…

硬件服务器基础

1、硬件服务器基础 2、服务器后面板 3、组件 3.1 CPU 3.2 内存 3.3 硬盘 3.4 风扇 4、服务器品牌 4.1 配置 4.2 CPU 架构 4.2.1 CPU 命名规则 4.2.2 服务器 CPU 和家用 CPU 的区别 4.2.3 CPU 在主板的位置 4.2.4 常见 CPU 安装方式 4.3 内存中组件 4.3.1 内存的分类 4.3.1.1 …

OpenWebUI(1)源码学习构建

1. 前言 通过docker镜像拉取安装就不介绍了&#xff0c;官方的命令很多。本节主要撸一撸源码&#xff0c;所以&#xff0c;本地构建 2. 技术框架和启动环境 后端python&#xff0c;前端svelte 环境要求&#xff1a;python > 3.11 &#xff0c;Node.js > 20.10 3. 源…

三方接口设计注意事项

前言 随着业务系统间集成需求的增加&#xff0c;三方接口设计已成为现代软件架构中的关键环节。一个设计良好的三方接口不仅能够提供稳定可靠的服务&#xff0c;还能确保数据安全、提升系统性能并支持业务的持续发展。 一、设计原则 1. 统一接口原则 三方接口设计应遵循统一…

CSS篇-5

1. 内联元素可以实现浮动吗? 是的,内联元素完全可以实现浮动。在 CSS 中,任何元素都可以被设置为浮动(float)。 当一个元素被设置了 float 属性后,无论它本身是块级元素还是内联元素,它都会表现出类似于块级元素的特性: 生成块级框(Block-level box):浮动元素会生…

RocketMQ 学习

消息队列 参考官方文档&#xff1a;https://rocketmq.apache.org/zh/docs/ 基本概念 主题&#xff08;Topic&#xff09;&#xff1a;是消息传输和消息存储的顶级容器&#xff0c;不是实际的消息容器&#xff0c;而是一个逻辑上的概念&#xff0c;用于区分不同业务消息的标识&…

Conda更换镜像源教程:加速Python包下载

Conda更换镜像源教程&#xff1a;加速Python包下载 为什么要更换conda镜像源&#xff1f; Conda作为Python的包管理和环境管理工具&#xff0c;默认使用的是国外镜像源&#xff0c;在国内下载速度往往较慢。通过更换为国内镜像源&#xff0c;可以显著提高包下载速度&#xff…

PCIe—TS1/TS2 之Polling.Active(一)

前文 训练序列有序集用于比特对齐、符号对齐以及交换物理层参数。2.5GT/s和5GT/s速率时&#xff0c;训练序列有序集不会加扰&#xff0c;只用8b/10b 编码。但到8GT/s及以上速率时&#xff0c;采用128b/130b编码&#xff0c;符号有可能加扰有可能不加扰&#xff0c;具体…

【HarmonyOS Next之旅】DevEco Studio使用指南(二十八) -> 开发云对象

目录 1 -> 开发流程 2 -> 创建云对象 3 -> 开发云对象 4 -> 调试云对象 4.1 -> 前提条件 4.2 -> 通过本地调用方式调试云对象 4.3 -> 通过远程调用方式调试云对象 5 -> 部署云对象 1 -> 开发流程 除去传统的云函数&#xff0c;您还可在端云…

基于51单片机的音乐盒汽车喇叭调音量proteus仿真

地址&#xff1a; https://pan.baidu.com/s/1l3CSSMi4uMV5-XLefnKoSg 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C51 是一款常用的 8 位单片机&#xff0c;由 Atmel 公司&#xff08;现已被 Microchip 收…

实验设计与分析(第6版,Montgomery)第5章析因设计引导5.7节思考题5.8 R语言解题

本文是实验设计与分析&#xff08;第6版&#xff0c;Montgomery著&#xff0c;傅珏生译) 第5章析因设计引导5.7节思考题5.8 R语言解题。主要涉及方差分析&#xff0c;正态假设检验&#xff0c;残差分析&#xff0c;交互作用图。 (a) dataframe<-data.frame( Lightc(580,568…