关于线性筛Euler欧拉函数的详细证明代码

news/2025/1/22 18:26:11/文章来源:https://www.cnblogs.com/FrankWKD/p/18679998

\[Designed\ By\ FrankWkd\ -\ Luogu@Lwj54joy,uid=845400 \]

引言:由于dsfz的集训老师讲的跟**一样太快了,蒟蒻前去听了洛谷网校@disangan233大佬的讲解,在此重构线性筛Euler函数的证明及代码。本文LateX较多,可能加载卡顿,请耐心等待.

关于Euler函数

  • \(Euler\) 函数,同时被称为欧拉函数, 定义: \(\varphi(n)\) 表示 \(\le n\) 且与 \(n\) 互质的数的个数
  • 我们规定:\(\varphi(1) = 1\)

Euler函数的性质

  • 积性:对于 \(gcd(a,b)=1\) 的两个数 \(a,b\) , $\varphi(a\times b)=\varphi(a)\times \varphi(b) $.
  • 欧拉反演:$\sum_{d|n}\varphi(d) = n $
  • 对于任意质数 \(p\)\(\varphi(p^k)=p^k-p^{k-1}\)

对于Euler函数性质的证明

  • 1:根据积性函数的定义可得。
  • 2:公式解释:对于每个是 \(n\) 的质因子的数 \(p\),把他们的 \(\varphi\) 全部加在一起的和是 \(n\).
    \(10\) 举例:\(10\) 的全部质因子为 \(\{2,3,5,7,9\}\) ,他们的 \(\varphi\)分别为: \(\{0,1,2,3,4\}\), 加起来就是原数 \(10\).
  • 3: 很显然,小于 \(p^k\) 的数中与 \(p\) 不互质的数仅有\(p,2p,3p\dots p^{k-1}p\).总数为 \(p^{k-1}\) 个.
    那小于它且与它互质的数的个数就是总数减去 \(p^{k-1}\) 个,即 \(\varphi(p^k)=\) 总数 \(-\ p^{k-1}\),即: \(\varphi(p^k)=p^k-p^{k-1}\)

求Euler函数

单个欧拉函数求法

  • 可以直接求出其唯一分解式然后求解(本人没太听懂,但是没关系,这一点用不到)

线性筛求Euler函数

  • 本文的重头戏来了!
  • 我们可以在线性筛求质数的同时求出每个数的Euler函数.\(p\)\(i\) 的最小质因子时,有三种情况:
    • 1: \(i\) 是质数: \(\varphi(i) = i-1\)
    • 2:\(p\)\(\frac{i}{p}\) 的质因子:\(\varphi(i)=p\times \varphi(\frac{i}{p})\)
    • 3: \(p\)\(\frac{i}{p}\)互质:$\varphi(i)=\varphi(p)\times \varphi(\frac{i}{p}) $.
  • 为什么要解决 \(\frac{i}{p}\)\(p\) 的关系呢?
    因为他们的乘积就是 \(i\) ,我们要求 \(\varphi(i)\),那么根据 \(Euler\) 函数的性质 \(1\) ,可以得出: \(\varphi(i)=\varphi(\frac{i}{p})\times \varphi(p)\) ,那么问题就变成了计算两个已知质数的 \(\varphi\) 的乘积.详见 板块【由数学到程序】

线性筛求Euler函数三种形式的证明

  • 1: 因为 \(i\) 为质数,由定义立得:\(\varphi(i) = i-1\)
  • 2: 设 \(i=p^kq\) ,其中 \(q\) 不含质因子 \(p\). 利用积性可得: \(\varphi(i)=\varphi(p^k)\times \varphi(q)\)
    利用 \(Euler\)函数性质三可得: \(\varphi(i)=\varphi(p^k) \times \varphi(q)=(p^k-p^{k-1})\times \varphi(q)\)
    提出公因式 \(p\) 可得: \(\varphi(i)=\varphi(p^k) \times \varphi(q)=(p^k-p^{k-1})\times \varphi(q)=p(p^{k-1}-p^{k-2})\times \varphi(q)\)
    \(Euler\) 函数性质三的逆运算可得: \(p(p^{k-1}-p^{k-2})\times \varphi(q)=p\times \varphi(p^{k-1})\times \varphi(q)\)
    \(Euler\) 函数性质一的逆运算可得: \(p(p^{k-1}-p^{k-2})\times \varphi(q)=p\varphi(p^{k-1})\times \varphi(q)=p\times \varphi(p^{k-1}\times q)\)
    根据除法的性质可得: \(p\times \varphi(p^{k-1}\times q)=p\times \varphi(\frac{i}{p})\)
    又因为 \(\varphi(i)=p\times \varphi(p^{k-1}\times q)\)
    所以得出: \(\varphi(i)=p\times \varphi(\frac{i}{p})\)
  • 3: 因为这二者互质,有积性立得: $\varphi(i)=\varphi(p)\times \varphi(\frac{i}{p}) $.
    OK,我们已经推完了数学部分!

由数学到程序

那么,如何应用到程序中呢?

  • 有几个条件:
    • 不同的量符合其性质(互质相等因数、大小关系等)
    • 等式成立。
  • 第一种情况非常简单,若 \(i\) 为质数,只要将他的 \(\varphi\) 设为 \(i-1\) 即可。在线性筛筛出质数时将它的 \(\varphi\) 设为其减一即可。
  • 第二、三种情况需要构造两个积为 \(i\) 的量,我们令他们分别为:\(p\)\(\frac{i}{p}\) 。因为 \(p\) 必须是 \(i\) 的最小质因子,所以它肯定是 \(primes\) 数组中的值,而且 \(i\) 由两个数的乘积构成,所以是合数。那线性筛中哪里可以筛除合数呢?双层 \(for\) 中!那么,我们已经确定了大致位置。
  • 情况二:

线性筛筛Euler函数代码(还没写完)

点击查看代码
#include <bits/stdc++.h>
int primes[101000], n, phi[101000]; //分别存储:素数,数据总数,i的欧拉函数
bool f[101000];//标记当前数是不是素数
void get_phi() {//设p是i的最小质因子,p为质数int cnt = 0;phi[1] = 1;for (int i = 2; i <= n; i++) {if (!f[i]) {primes[++cnt] = i;phi[i] = i - 1; //对应情况一}for (int j = 1; j <= cnt and primes[j]*i <= n; j++) {f[i * primes[j]] = true;/*在此for循环中,i的定义发生了转移,由var_i*primes[j]来表示i,那么var_i与primes[j]就理所当然地成为了i的因子。由于primes[j]不可能比var_i更大(因为大于i的质数还没筛到)s所以primes[j]符合公式中p的定义。而var_i呢?它很被动,必须保证与p的乘积为i,所以干脆把var_i在数学公式中定义为i/p*/if (i % primes[j] == 0) {phi[i * primes[j]] = phi[i] * primes[j];break;}else{phi[i * primes[j]] = phi[i] * phi[primes[j]];}}}
}int main() {std::cin >> n;get_phi();for(int i = 1;i <= n;i++){std::cout<<phi[i]<<std::endl;}
}

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

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

相关文章

Android图形层垂直同步虚拟VSYNC机制

简介 某次调图形性能的时候(启动后台录屏,下(或)称case)发现Android SurfaceFlinger Vsync机制并没有以前想的这么简单粗糙,特别是这次调图形性能发现一些跟Vsync有关联,因此做个总结详解。 跟不上旋律节奏的VSYNC 一份追踪报告,发现Vsync信号非常不规律,于是从这里入手…

[日志] 打印异常堆栈信息的技巧

序Java的异常堆栈信息,对提升排查问题的效率,有极大的帮助————便于我们快速定位异常的发生过程和发生异常的代码行。本文使用的日志框架slf4j : 1.7.25 log4j(2) : 2.20.0 日志行的打印策略 : log4j2.properties# property.log.layout.consolePattern=%d{yyyy/MM/dd HH:m…

【vjudge训练记录】大一寒假专项训练——前缀和/差分

训练情况A题 前缀和模板题,我们输入完 \(a_i\) 后直接求前缀和 \(a_i = a_i + a_{i-1}\),求区间 \([l,r]\) 的和就为 \(a_r-a_{l-1}\)点击查看代码 #include <bits/stdc++.h> #define int long long #define endl \nusing namespace std;void solve(){int n,m;cin>&…

VSCode使用之go语言配置

时间:2025/1/22 扩展:go 目的:支持go语言,方便安装其他必备插件安装该扩展包后可以执行该扩展包提供的命令Go:Install/Update Tools来进一步扩展go工具执行命令的窗口可以通过Ctrol+Shift+P调出点击后会出现很多选项,可以根据自己需要勾选然后点击确定,等待下载安装,一般情…

VSCode设置之默认在当前文件目录下打开终端

在vscode界面依次点击“文件”→“首选项”→“设置”→“用户”→“功能”→“终端”,找到Integrated:Cwd选项,将其值修改为”${fileDirname}“,即可在所有打开的工程内实现终端默认在当前文件的路径启动

树上的轮廓线DP!——AGC017F Zigzag

树上的轮廓线DP!——AGC017F Zigzag 注意到 \(n,m\le 20\),考虑状压,设 \(f_{i,S}\) 表示对于第 \(i\) 条线,其路线为 \(S\) 的方案数。 转移需要枚举 \(f_{i-1,S}\) 复杂度 \(\mathcal O(4^n\text{poly}(n))\)。 发现这种相邻状态之间的限制很像矩形中行的扩展,于是我们可…

使用 CSS flex(横向) 实现瀑布流布局(需要后端配合数据分左右)

核心代码(提供思路)<up-waterfall v-model="flowList"><template v-slot:left="{leftList}"><view v-for="(item, index) in leftList" :key="index"><!-- 这里编写您的内容,item为您传递给v-model的数组元素…

htb LinkVortex walkthrough

nmapnmap -p- -A -sS -T 4 10.10.11.47 Starting Nmap 7.95 ( https://nmap.org ) at 2025-01-22 00:58 UTC┌──(root㉿kali)-[/home/ftpuserr] └─# nmap -p- -A -sS -T4 10.10.11.47 Starting Nmap 7.95 ( https://nmap.org ) at 2025-01-22 00:58 UTC Stats: 0:02:28 ela…

网络抓包文件太大,如何切分

背景 节前最后几天了,随便写点水文吧,今天就记录一下,当我们拿到的网络抓包文件太大,应该怎么分析。 一般来说,我们个人抓包的话,linux上用tcpdump比较多,抓的时候也会用捕获表达式,抓出来的包一般不大,用wireshark分析就很容易。 但是,前一阵的一个晚上,dba突然找我…

java进程内存占用分析

一、背景 1.1 问题描述 不知道大家在开发过程中有没有遇到过类似的问题,明明通过JVM参数-Xmx256m设置了最大堆内存大小为256m,但是程序运行一段时间后发现占用的内存明显超过了256m,却并没有出现内存溢出等问题,那是什么东西占用了额外的内存空间呢? 通过ps查看java进程项…

《ESP32-S3使用指南—IDF版 V1.6》第三章 ESP32-S3基础知识

第三章 ESP32-S3基础知识 1)实验平台:正点原子DNESP32S3开发板 2)章节摘自【正点原子】ESP32-S3使用指南—IDF版 V1.6 3)购买链接:https://detail.tmall.com/item.htm?&id=768499342659 4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/esp3…