线性筛与欧拉函数 笔记
本文原在 2024-02-24 14:16 发布于本人洛谷博客。
一、线性筛
易发现时间复杂度为 \(O(n\sqrt n)\) 的埃式筛法存在缺陷:一个数有可能被多个质数筛掉。
如 \(24\),他在 \(2\times 12\) 时被筛了一遍,\(3\times 8\) 时又被筛了一遍,十分浪费时间。
线性筛就是让每个数只会被一个质数筛去,这个质数就是被筛的合数的最小质因子。
算法代码:
namespace Eular{ int prime[N],tot; bool isprime[N]; void eular(int x){ memset(isprime,true,sizeof isprime); isprime[1]=false; for(int i=2;i<=x;i++){ if(isprime[i])prime[++tot]=i; for(int j=1;j<=tot and i*prime[j]<=x;j++){ isprime[i*prime[j]]=false; if(!(i%prime[j]))break; } } } }using namespace Eular;
为什么当 \(i\bmod prime_j=0\) 时,就可以进入下一个合数了呢?
举例:当 \(i=21\) 时,\(prime=\{0,2,3,5,7,11,13,17,19\}\)。
当遍历到 \(prime_2\) 时,\(21=3\times 7\),如果此时不停止 \(21\) 的工作,那么下一个被筛的数 \(5\times 21=105\) 就是被 \(5\) 筛掉的,而显然的,根据线性筛工作的原理,\(105\) 应该被 \(3\times(7\times 5)\),也就是 \(3\times 35\) 筛。
二、欧拉函数
1. 定义
欧拉函数 \(\varphi(n)\) 表示小于等于 \(n\) 且与 \(n\) 互质的正整数个数。
如 \(\varphi(12)=4\)(\(1\),\(5\),\(7\),\(11\))。
特别的,\(\varphi(1)=1\)。
2. 解法
可以用容斥原理很快的求出来。
如求 \(12\) 的,用 \(A_i\) 表示小于等于 \(12\) 的数中,\(i\) 的倍数的个数,那么答案为 \(+A_1-A_2-A_3+A_{2\times3}\)。
理解例子后,再求更通用的公式:
分解 \(n\) 的质因子,设 \(n=p_1^{t_1}p_2^{t_2}p_3^{t_3}\dots p_m^{t_m}\),其中序列 \(p\) 的数全为质数且不重复。
设 \(A_i\) 表示小于等于 \(n\) 且是 \(p_i\) 的倍数的自然数集合,则 \(|A_i|=\left\lfloor \dfrac{n}{p_i}\right\rfloor\)(\(1\le i\le m\))。
因 \(p\) 序列中全为质数,所以 \(p\) 里的所有数互质,所以 \(p_i\) 与 \(p_j\) 的最小公倍数是 \(p_ip_j\),所以 \(|A_i\cap A_j|=\dfrac{n}{p_ip_j}\)(\(i\ne j,1\le i,j\le m\))。
由容斥原理,可得:
3. 定理
(1). 若 \(n\) 是质数,\(\varphi(n)=n-1\)。
因为 \(n\) 是质数,那么 \(n\) 的分解质因数为:\(p=\{n\}\)。
\(\therefore\varphi(n)=n(1-\dfrac{1}{n})=n-1\)
(2). 已知 \(q\) 是质数,若 \(n\bmod q=0\),则 \(\varphi(nq)=q\varphi(n)\),否则 \(\varphi(nq)=(q-1)\varphi(n)\)。
先证明第一点。
用同第二章第 \(2\) 节的方法分解 \(n\) 的质因子得到序列 \(p\)。
\(\because n\bmod q=0\),且 \(q\) 是质数,
\(\therefore q\in p\)。
将 \(q\) 从集合 \(p\) 中删去。
\(\therefore \varphi(nq)=nq(1-\dfrac{1}{q})\prod_{i=1}^m(1-\dfrac{1}{p_i})\),
\(q\varphi(n)=qn(1-\dfrac{1}{q})\prod_{i=1}^m(1-\dfrac{1}{p_i})\)。
\(\therefore \varphi(nq)=q\varphi(n)\)。
再证明第二点。
同理得到 \(p\),但此时 \(q\notin p\)。
\(\therefore \varphi(nq)=nq(1-\dfrac{1}{q})\prod_{i=1}^m(1-\dfrac{1}{p_i})=(nq-n)\prod_{i=1}^m(1-\dfrac{1}{p_i})\),
\((q-1)\varphi(n)=(q-1)n\prod_{i=1}^m(1-\dfrac{1}{p_i})=(nq-n)\prod_{i=1}^m(1-\dfrac{1}{p_i})\)。
\(\therefore \varphi(nq)=(q-1)\varphi(n)\)。
三、积性函数
1. 定义
若在正整数域中一个函数 \(f(x)\) 对于任意 \(\gcd(x,y)=1\) 的 \(x\),\(y\) 都满足 \(f(xy)=f(x)f(y)\),则称 \(f(x)\) 是一个积性函数。
2. \(O(n)\) 求 \(\varphi(1)\sim\varphi(n)\)
(1). 证明 \(\varphi(x)\) 是积性函数
设 \(n\) 与 \(m\) 互质,他们的质因子的数列分别是 \(pn\),\(pm\),且个数分别为 \(cntn\),\(cntm\)。
因为 \(n\) 与 \(m\) 互质,所以 \(pn\) 与 \(pm\) 里的数互不相同。
则 \(\varphi(n)\varphi(m)\)
\(=nm\prod_{i=1}^{cntn}(1-pn_i)\prod_{i=1}^{cntm}(1-pm_i)\)
\(=\varphi(nm)\)。
(2). 解法
设 \(q\) 是 \(nq\) 的最小质因子,由第二章第 \(3\) 节的定理可得:
\(\varphi(nq)=\left\{\begin{matrix} n-1&n=q\\ q\varphi(n)&n\bmod q=0\\ (q-1)\varphi(n)&n\bmod q\ne0 \end{matrix}\right.\)
这样就可以一边欧拉筛一边递推了。
namespace Phi{ int prime[N],tot,phi[N]; bool isprime[N]; void getphi(int x){ memset(isprime,true,sizeof isprime); isprime[1]=false; phi[1]=1; for(int i=2;i<=x;i++){ if(isprime[i]){ prime[++tot]=i; phi[i]=i-1; } for(int j=1;j<=tot and i*prime[j]<=x;j++){ isprime[i*prime[j]]=false; if(i%prime[j])phi[i*prime[j]]=(prime[j]-1)*phi[i]; else{ phi[i*prime[j]]=prime[j]*phi[i]; break; } } } } }using namespace Phi;
3. 更多积性函数:\(d(x)\)
(1). 定义
(2). 证明 \(d(x)\) 是积性函数
(3). 解法
本文作者:Garbage fish's Blog
本文链接:https://www.cnblogs.com/Garbage-fish/p/18709896
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步