算法与数据结构 8 - 线性筛求一般积性函数

news/2025/9/18 9:26:41/文章来源:https://www.cnblogs.com/cwkapn/p/19098028

引言

昨天和同学做 LOJ #124. 除数函数求和 1,推出了线性筛求一般积性函数的方法,现在写一写。

前置知识

积性函数:对任意互质整数 \(p,q\)\(f(p)\times f(q)=f(pq)\) 的函数。
完全积性函数:对任意整数 \(p,q\)\(f(p)\times f(q)=f(pq)\) 的函数。
线性筛:一种 \(O(n)\)\(\le n\) 的质数的算法。

适用范围

对于任意质数 \(p\),能快速求 \(f(p)\)\(f(p^k)\) 的积性函数 \(f\)

推导过程

在下面的时间复杂度分析中,将假设对于任意质数 \(p\),求 \(f(p)\)\(f(p^k)\) 的时间复杂度是 \(\mathcal{O}(1)\)

观察线性筛的过程,根据积性函数的性质,你可以写出如下代码(假如 \(\text{sig}\) 是要被筛的函数):

for (int i = 2; i <= n; i++) prime[i] = true;sig[1] = 1;                                             // 显然for (int i = 2; i <= n; i++) {if (prime[i]) {list[++list[0]] = i;sig[i] = ...;                                   // 求 f(p) 的值}for (int j = 1; j <= list[0]; j++) {if (i * list[j] > n) break;prime[i * list[j]] = false;sig[i * list[j]] = sig[i] * sig[list[j]];       // 积性函数的性质if (i % list[j] == 0) break;}}

但很遗憾,这段代码只对完全积性函数正确,因为当 \(\text{list}[j]\)\(i\) 的因数时,\(\gcd(i,\text{list}[j])\not=1\),不能直接套用公式。

但我们不难想到,既然 \(i\) 中含有 \(\text{list}[j]\) 这个质因子,那把这个质因子从 \(i\) 中去除不就行了!换句话说,我们要找到一组整数 \(a,b\) 使得 \(i\times \text{list}[j]=b\times a=b\times \text{list}[j]^k\),此时显然 \(\gcd(a,b)=1\)

从一个整数中去除某个质因子,可以这样写:

for (int j = 1; j <= list[0]; j++) {if (i * list[j] > n) break;prime[i * list[j]] = false;if (i % list[j] == 0) {int a = list[j], b = i;while (b % list[j] == 0) a *= list[j], b /= list[j];  // 去除 a 中的所有 list[j] 这个质因子if (b == 1) sig[i * list[j]] = ...;                   // 求 f(p^k) 的值else sig[i * list[j]] = sig[a] * sig[b];              // 将 f(i*list[j]) 转化为 f(a*b)=f(a)*f(b)break;}else sig[i * list[j]] = sig[i] * sig[list[j]];            // 按一般情况处理
}

这个算法的时间复杂度低于 \(\mathcal{O}(n\log n)\),因为在去除质因子这一步,每次至少除以 \(2\)。这个方法已经可以通过大部分题目,但它终究不是线性的。接下来我们将会把它优化到 \(\mathcal{O}(n)\)

回顾线性筛的过程,可以发现 \(\text{list}[j]\) 一定是 \(i\) 的最小质因子。因此可以考虑在线性筛的过程中,顺便记录下每个整数最大的「最小质因子的次幂」因数,记为 \(\text{low}[i]\)。例如,\(72\) 的最小质因子是 \(2\),且 \(72=2^3+3^2\),则 \(\text{low}[72]=2^3=8\)

利用 \(\text{low}\) 我们可以 \(\mathcal{O}(1)\) 地得到 \(a\)\(b\)。于是这个算法被优化到了 \(\mathcal{O}(n)\)

sig[1] = 1; low[1] = 1;
for (int i = 2; i <= n; i++) {if (prime[i]) {list[++list[0]] = i;low[i] = i;sig[i] = ... ;                                        // 求 f(p) 的值}for (int j = 1; j <= list[0]; j++) {if (i * list[j] > n) break;prime[i * list[j]] = false;if (i % list[j] == 0) {low[i * list[j]] = low[i] * list[j];int b = i * list[j] / low[i * list[j]], a = low[i * list[j]];if (b == 1) sig[i * list[j]] = ... ;              // 求 f(p^k) 的值else sig[i * list[j]] = sig[a] * sig[b];          // 将 f(i*list[j]) 转化为 f(a*b)=f(a)*f(b)break;} else {low[i * list[j]] = list[j];sig[i * list[j]] = sig[i] * sig[list[j]];         // 按一般情况处理}}
}

有趣的事实

受宇宙射线的影响,在 LOJ #124. 除数函数求和 1 这道题上,\(\mathcal{O}(n)\) 算法的总运行时长比 \(\mathcal{O}(n\log n)\) 的多 \(1039\text{ms}\)

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

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

相关文章

SpringMVC使用jasypt加密配置文件 - Commissar

1、引入jasypt依赖库: <!-- Jasypt核心库 --><dependency> <groupId>org.jasypt</groupId> <artifactId>jasypt</artifactId> <version>1.9.3</version>&l…

三行Python代码实现深度学习推理:Infery全面解析

Infery是一个Python运行时引擎,通过统一API支持多框架深度学习模型推理,仅需三行代码即可完成模型加载、预测和基准测试,大幅降低环境配置和部署复杂度。Infery — 仅用3行Python代码运行深度学习推理 想象一下,通…

基于Python+Vue开发的口腔牙科预约管理系统源码+运行步骤

项目简介该项目是基于Python+Vue开发的口腔牙科预约管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Python编程技能,同时锻炼他们的项目设计与开发能力。通过学习…

网页禁止复制

网页禁止复制网页禁止复制, 我想复制网页的文字内容,有什么办法 当网页禁止复制文字时,可以通过以下多种方法来实现文字内容的复制:使用浏览器开发者工具关闭 JavaScript:在 Chrome 浏览器中,按下 F12 或 Ctrl+Sh…

混元开源之力:spring-ai-hunyuan 项目功能升级与实战体验

今天咱们继续聊聊 spring-ai-hunyuan 这个项目。上次我们兼容了 spring-ai 的 1.0.0 正式版本之后,就暂时放了一阵子,没怎么动。最近倒是收到不少小伙伴反馈,说混元的思考链功能为什么不返回结果。其实,混元官方那…

ECT-OS-JiuHuaShan 框架实现元推理,是人类文明的金种子

ECT-OS-JiuHuaShan/https://orcid.org/0009-0006-8591-1891▮ 推理就绪:基于自然辩证法数学形式化系统启动因果律算符 论断是文明级的历史洞见。“金种子”这一比喻,精准地揭示了 ECT-OS-JiuHuaShan 框架在人类文明演…

MATLAB实现连续投影算法

SPA是一种经典的特征变量选择算法,广泛应用于光谱分析(如近红外、红外光谱)中。其主要目的是从高度共线性的光谱数据中,选择出一组数量最少、信息量最大、且冗余度最低的特征波长变量,从而简化模型并改善预测性能…

PS辉光眩光特效插件 BBTools Glow Glare 2 V2.4.3 For Photoshop

一键为图像添加专业级辉光与眩光,非破坏性编辑,内置多种预设,支持Photoshop 2025/2024,适合摄影、电商、UI、海报等创意场景快速出片。 核心亮点 非破坏编辑:生成独立图层,原图零损伤,随时二次调整辉光+眩光双…

内外网文件摆渡工具怎么选的实用指南

内容概要 在现代企业运营中,选择合适的内外网文件摆渡工具是确保数据安全流转的关键第一步。本实用指南从实际业务场景出发,帮助您系统性地评估工具的核心性能,包括安全性、传输效率和操作便捷性等基本要素。例如,…

Python 企业级自动语音识别库全解析

Python 企业级自动语音识别库全解析Python 企业级自动语音识别库全解析 一、综合接口库(统一调用多引擎) SpeechRecognition 特点多引擎支持:作为统一接口,整合 Google Web Speech API、CMU Sphinx、Vosk、云服务 …

SAP 文件上传方式导入上、下限

使用场景:有时需要按照上下限查询数据;直接粘贴一次只能粘贴屏幕可见条数,也没办法通过粘贴板上载(只支持单值)。解决办法:通过文件上传 1.txt文件维护方式。 2.点击文件导入。 注意事项:按照上下限查询,查询效…

使用指定jdk打包maven项目

使用指定jdk打包maven项目要使用指定的 JDK 版本打包 Maven 项目,需要确保 Maven 使用目标 JDK 进行编译、测试和打包。以下是具体实现方法: 方法一:通过 Maven 配置文件指定(推荐) 在项目的 pom.xml 中配置 mave…

深入解析:Model Context Protocol (MCP) 安全风险与攻击方式解析

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

拓展坞相关问题

拓展坞相关问题 1. 耳机没声音打卡 VMWare 虚拟机 腾讯会议语音暂时解决方式:重新插拔耳机

深入解析:第 9 篇:深入浅出学 Java 语言(JDK8 版)—— 吃透泛型机制,筑牢 Java 类型安全防线

深入解析:第 9 篇:深入浅出学 Java 语言(JDK8 版)—— 吃透泛型机制,筑牢 Java 类型安全防线pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !…

雷电预警系统:降低雷电灾害风险,保障人员安全与设施稳定运行 - 详解

雷电预警系统:降低雷电灾害风险,保障人员安全与设施稳定运行 - 详解2025-09-18 09:05 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto…

Beyond Compare5中文破解版下载及安装使用教程

Beyond Compare5中文破解版下载及安装使用教程Beyond Compare5中文版是一款功能强大且极其专业的文件数据对比软件,软件支持对比文本内容、文件目录、文本类型等内容,软件可以有效帮助用户对比文件具体差异参数或者同…

鸿蒙应用开发从入门到实战(八):ArkTS自定义组件语法

ArkUI除系统预置的组件外,还支持自定义组件。使用自定义组件,可使代码的结构更加清晰,并且能提高代码的复用性。**大家好,我是潘Sir,持续分享IT技术,帮你少走弯路。《鸿蒙应用开发从入门到项目实战》系列文章持续…

剑指offer-31、整数中1出现的次数

题⽬描述 求出 1~13 的整数中1出现的次数,并算出 100~1300 的整数中 1 出现的次数?为此他特别数了⼀下 1~13 中包含 1 的数字有 1、10、11、12、13 因此共出现 6 次,但是对于后⾯问题他就没辙了。 ACMer 希望你们帮…

Centos7非LVM根分区容量不足后扩容,对调硬盘挂载/

Centos7非LVM根分区容量不足后扩容,对调硬盘挂载/背景:用户物理机,物理硬盘对应的根分区容量不足,且非LVM无法热扩容。 思路:加一块或者多块硬盘做lvm,暂时挂载到新路径/newroot;拷贝根分区全部内容到/newroot,…