1080 字
5 分钟

数论补完计划 Part3 欧拉函数

2024-09-18
2024-09-18
浏览量 加载中...

欧拉函数#

欧拉函数 φ(x)\varphi(x),表示 [1,x][1,x] 内与 xx 互质的数的个数。对于质数 pp 显然有 φ(p)=p1\varphi(p)=p-1。特殊地,φ(1)=1\varphi(1)=1。欧拉函数是一个积性函数,对任意互质的数 a,ba,b,都有 φ(ab)=φ(a)φ(b)\varphi(ab)=\varphi(a)\cdot\varphi(b)。不互质时,如果 xx 为奇数,那么有 φ(2n)=φ(n)\varphi(2n)=\varphi(n)

如果 xx 可以用算术基本定理分解成 i=1kpici\prod\limits_{i=1}^{k}p_i^{c_i} 的形式,那么 φ(x)=x(11p1)(11p2)(11pk)=xi=1k(11pk)\varphi(x)=x(1-\frac{1}{p_1})(1-\frac{1}{p_2})\dots(1-\frac{1}{p_k})=x\prod\limits_{i=1}^{k}(1-\frac{1}{p_k})。注意,若 xx 可以被同一个质数反复除尽,即存在一个 pip_it>1t>1 使得 pitxp_i^t\mid x,计算时同样只对这个质数计算一次贡献。

证明:

正难则反,考虑用 [1,n][1,n] 内的所有数的个数减去不互质的数的个数。

因为每个大于 1{1} 的自然数都可以分解为若干质数之积,因此我们只需要考虑小于等于 nn 的所有质因子,这一步类似于埃氏筛的想法。那么能被 pp 整除的数就有 np\lfloor\frac{n}{p}\rfloor 个,进而,得到第一个式子:

m=ni=1knpkm=n-\sum\limits_{i=1}^k\lfloor\frac{n}{p_k}\rfloor

但是有一个小问题——如果 n=p1mp2nn=p_1^mp_2^n 或诸如此类的数,那么在计算贡献时会被 p1p_1p2p_2 同时计入,显然结果小于正确答案。此时我们就需要引入“容斥原理”来帮我们解决这个问题了。来看一个例子(小学奥数题):

假设被 2,3,5{2,3,5} 整除的数分别构成三个集合 A2,A3,A5A_2,A_3,A_5,那么我们在用 card(A2)+card(A3)+card(A5)\operatorname{card}(A_2)+\operatorname{card}(A_3)+\operatorname{card}(A_5) 计算结果时(card\operatorname{card} 记号表示集合元素个数),两个集合间的交集部分总共会被计入两次,最中间三个集合的交集总共会被计入三次,而我们希望的是每个部分只计一次。此时可以用上边算出的和减去两两集合之间的交集,那么最中间又会被减去三次,因而最终再加上一次中间部分,就得到了正确答案。也就是说本例的结果为:

x=card(A2)+card(A3)+card(A5)card(A2A3)card(A2A5)card(A3A5)+card(A2A3A5)x=\operatorname{card}(A_2)+\operatorname{card}(A_3)+\operatorname{card}(A_5)-\operatorname{card}(A_2\cap A_3)-\operatorname{card}(A_2\cap A_5)-\operatorname{card}(A_3\cap A_5)+\operatorname{card}(A_2\cap A_3\cap A_5)

特别的,形如上例问题的结果可以用以下公式算出:

x=i=1kj=1(ki)(1)i1card(AtAsAqi items in total)x=\sum\limits_{i=1}^{k}\sum_{j=1}^{\binom{k}{i}}(-1)^{i-1}\operatorname{card}(\underbrace{A_t\cap A_s\cap\dots\cap A_q}_{i~\text{items in total}})

因此我们在欧拉函数的计算中,也可以引入容斥原理。我们需要加上能被任意两个不同质数之积整除的数的个数,再减去能同时被三个不同质数之积整除的,以此类推。最终经过一些奇妙的化简(或者根本就是猜了一个结果然后拆括号检验的,正难则反懂不懂),得到如下计算公式:

φ(x)=xi=1k(11pi)\varphi(x)=x\prod\limits_{i=1}^k(1-\frac{1}{p_i})

代码实现时,通常把 11p{1-\frac{1}{p}} 等价变形为 p1p\frac{p-1}{p},然后先除后乘,以保证整除。

int eular(int x) {
int res = x;
for (int i = 2; i * i <= x; i++) {
if (x % i == 0) {
res = res / i * (i - 1);
while (x % i == 0) x /= i;
}
}
if (x > 1) res = res / x * (x - 1);
return res;
}

欧拉函数的递推#

本质是在筛质数的过程中顺便维护一定区间内的数的欧拉函数值,这就需要用到欧拉函数作为积性函数的性质了。

线性筛/埃氏筛在筛质数的过程中,有一步是标记掉质数的所有倍数,根据算术基本定理,所有合数都可以被如此标记掉。假如当前在筛 kpikp_i,大部分情况下 kpik\perp p_i 是可以保证的,此时 φ(kpi)=φ(k)φ(pi)=φ(k)×(pi1)\varphi(kp_i)=\varphi(k)\varphi(p_i)=\varphi(k)\times(p_i-1)。在这两种质数筛中,有一个特殊情况是 pikp_i\mid k,此时 φ(kpi)=φ(k)×pi\varphi(kp_i)=\varphi(k)\times p_i。总的时间复杂度是线性的。

int phi[N], primes[N];
bool st[N];
int idx = 0;
void sieve(int lim) {
phi[1] = 1;
for (int i = 2; i <= lim; i++) {
if (!st[i]) {
primes[++idx] = i;
phi[i] = i - 1;
}
st[i] = true;
for (int j = 1; i * primes[j] <= lim; j++) {
phi[i * primes[j]] = phi[i] * (primes[j] - 1);
st[i * primes[j]] = true;
if (i % primes[j] == 0) {
phi[i * primes[j]] = phi[i] * primes[j];
break;
}
}
}
}

欧拉函数的实例#

一个排列整齐的点阵,请问从某个角看去,视野内总共有多少个点?(不包括自己)

观察可得,图是有对称性的。那么沿对角线划分成上下两个对称的部分,对于两个点 (a,b)(a,b)(m,n)(m,n),显然当 a,ba,b 互质且 m,nm,n 互质时才能为答案贡献 2{2}。因此只需求互质对的数目即可,答案就是 2i=1n1φ(i)+1{2}\sum\limits_{i=1}^{n-1}\varphi(i)+1

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!

赞助
数论补完计划 Part3 欧拉函数
https://justpureh2o.cn/articles/37074/
作者
JustPureH2O
发布于
2024-09-18
许可协议
CC BY-NC-SA 4.0
最后更新于 2024-09-18,距今已过 515 天

部分内容可能已过时

评论区

Profile Image of the Author
JustPureH2O
穷方圆平直之情,尽规矩准绳之用
公告
JustPureH2O 的博客现已正式迁移至 Astro!原 Hexo 网站将移至 https://hexo.justpureh2o.cn/
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
100
分类
12
标签
54
总字数
368,990
运行时长
0
最后活动
0 天前

目录