欧拉函数详解

本文详细介绍了欧拉函数的基础概念,包括定义、基本性质和计算方法,并探讨了欧拉定理及其扩展形式。文章提供了O(n)和O(nloglogn)两种求解欧拉函数的算法,并通过例题展示了欧拉函数在数论问题中的应用,如求解GCD问题。此外,文章还提到了与费马小定理的关系及实际题目中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0.食用指北

  1. ( a , b ) (a,b) (a,b) 表示 gcd ⁡ ( a , b ) \gcd(a,b) gcd(a,b) ,也就是 a a a b b b 的最大公约数;
  2. [ a , b ] [a,b] [a,b] 表示 lcm ⁡ ( a , b ) \operatorname{lcm}(a,b) lcm(a,b) ,也就是 a a a b b b 的最小公倍数;
  3. i n v ( a , b ) inv(a,b) inv(a,b) 表示 a a a 在膜 b b b 意义下的逆元;
  4. p p p 的简化剩余系是什么?
    当且仅当 ( x , p ) = 1 且 x < p (x,p)=1且x<p (x,p)=1x<p 时, x x x 属于 p p p 的简化剩余系。
  5. [ x , y ) [x,y) [x,y) 表示左闭右开的区间;
  6. 重要结论均用红色突出了,可以重点阅读这些部分;
  7. 2.3前,你需要知道线性筛。

1.欧拉函数基础概念

1.1 欧拉函数的定义

欧拉函数表示一个数的简化剩余系的元素数。
或者说, 对 于 一 个 数 p , 它 的 欧 拉 函 数 值 即 为 [ 1 , p ) ∩ Z 内 与 p 互 质 的 数 的 个 数 。 \color{red}对于一个数 p ,它的欧拉函数值即为 [1,p)\cap\Z 内与 p 互质的数的个数。 p[1,p)Zp
特 殊 地 , 1 的 欧 拉 函 数 值 是 1 。 \color{red}特殊地,1 的欧拉函数值是 1 。 11
欧 拉 函 数 的 数 学 符 号 写 作 ϕ , 手 写 体 为 φ 。 \color{red}欧拉函数的数学符号写作 \phi ,手写体为 \varphi 。 ϕφ

1.2 欧拉函数的基本性质

  • 1.2.1 钦定 φ ( 1 ) = 1 \varphi(1)=1 φ(1)=1.
  • 1.2.2 若 p 为 质 数 , 则 φ ( p ) = p − 1. \color{red}若p为质数,则\varphi(p)=p-1. pφ(p)=p1.
  • 1.2.3 若 p p p 为质数,则 φ ( p k ) = p k − p k − 1 \varphi(p^k)=p^k-p^{k-1} φ(pk)=pkpk1.
  • 1.2.4 欧 拉 函 数 是 积 性 函 数 , 也 就 是 说 若 ( M , N ) = 1 , 则 φ ( M N ) = φ ( M ) φ ( N ) . \color{red}欧拉函数是积性函数,也就是说若(M,N)=1,则 \varphi(MN)=\varphi(M)\varphi(N). (M,N)=1φ(MN)=φ(M)φ(N).
  • 1.2.5 欧 拉 函 数 的 计 算 公 式 : φ ( x ) = x × ∏ i = 1 n ( 1 − 1 p i ) , 其 中 p 1 , p 2 , … , p n 为 x 的 所 有 质 因 数 . \color{red}欧拉函数的计算公式: \varphi(x)=x\times\prod\limits_{i=1}^n(1-\dfrac 1{p_i}),其中p_1,p_2,\dots,p_n为x的所有质因数. φ(x)=x×i=1n(1pi1)p1,p2,,pnx.
  • 1.2.6 若 p p p 为质数, x   m o d   p = 0 x \bmod p=0 xmodp=0,则 φ ( x p ) = φ ( x ) × p \varphi(xp)=\varphi(x)\times p φ(xp)=φ(x)×p
  • 1.2.7 若 p p p 为质数, x   m o d   p ≠ 0 x \bmod p\ne 0 xmodp=0,则 φ ( x p ) = φ ( x ) φ ( p ) \varphi(xp)=\varphi(x)\varphi(p) φ(xp)=φ(x)φ(p)
  • 有兴趣的话可以看看:以上七点的证明

2.欧拉函数的求法

2.1 O ( n ) 求 φ ( n ) \color{red}\mathcal O(\sqrt n) 求 \varphi(n) O(n )φ(n)

根据 1.2.5 的公式就可以做到啦

int zch_txdy(int n) {
	int ans=n,n2=n;
	for (int i=2; i*i<=n2; ++i) { //枚举√n2以下的质因子
		if (n2%i==0) ans=ans/i*(i-1); //先做除法,防止溢出
		while (n2%i==0) n2/=i;
	}
	if (n2>1) ans=ans/n2*(n2-1); //单独处理√n2以上的质因子
	return ans;
}

2.2 O ( n log ⁡ log ⁡ n ) \mathcal O(n\log\log n) O(nloglogn) φ ( 1 ) ∼ φ ( n ) \varphi(1)\sim \varphi(n) φ(1)φ(n)

依然和 1.2.5 的公式有关。 φ ( x ) = x × ∏ i = 1 n ( 1 − 1 p i ) \varphi(x)=x\times\prod\limits_{i=1}^n(1-\dfrac 1{p_i}) φ(x)=x×i=1n(1pi1)
其中 x x x 这一项无论如何都会乘上的,所以我们可以这样初始化:
for (int i=1; i<=n; ++i) phi[i]=i;
p i p_i pi x x x因子,所以我们可以用满足 p ∣ x p|x px 的质数 p p p 去筛 x x xphi[x]=phi[x]/p*(p-1)

int phi[500010];
void zch_ddjxd(int n) {
	for (int i=1; i<=n; ++i) phi[i]=i;
	for (int i=2; i<=n; ++i)
		if (phi[i]==i) //未被其它数筛过,说明它是质数
			for (int j=i; j<=n; j+=i) //用i去筛所有i的倍数
				phi[j]=phi[j]/i*(i-1);
}			

容易看出这份代码和埃氏筛法的时间复杂度相同,也是 O ( n log ⁡ log ⁡ n ) \mathcal O(n \log \log n) O(nloglogn)

2.3 O ( n ) 求 φ ( 1 ) ∼ φ ( n ) \color{red}\mathcal O(n)求\varphi(1)\sim\varphi(n) O(n)φ(1)φ(n)

线性筛的过程中加几句话就可以求欧拉函数了。具体看代码吧。
v v v 存的是一个附带信息( i i i 的最小质因子),读者可以不管。

const int N=1000010;
int cnt,v[N],p[N],phi[N];
void zch_AKIOI(int n) { //可筛素数、求欧拉函数
	for (int i=2; i<=n; ++i) {
		if (!v[i]) {
			p[++cnt]=i; //筛素数
			phi[i]=i-1; //1.2.2
			v[i]=i;
		}
		for (int j=1; j<=cnt; ++j) {
			if (1ll*p[j]*i>n) break; //当心爆int
			int t=p[j]*i;
			v[t]=p[j]; //t的最小质因子是p[j]
			if (i%p[j]==0) {
				phi[t]=phi[i]*p[j]; //1.2.6
				break; //每个数只被它的最小质因子筛一次
			}
			else phi[t]=phi[i]*phi[p[j]]; //1.2.7
		}
	}
}

3. 欧拉定理

若 a , p 为 一 对 互 质 的 正 整 数 , 则 a φ ( p ) ≡ 1 ( m o d p ) . \color{red} 若 a,p 为一对互质的正整数,则 a^{\varphi(p)} \equiv 1 \pmod p. a,paφ(p)1(modp).

证明:
p p p 的简化剩余系为 X X X ,元素记作 x 1 , x 2 , … , x φ ( p ) x_1,x_2,\dots,x_{\varphi(p)} x1,x2,,xφ(p)
先来证明 ∏ i = 1 φ ( p ) x i ≡ ∏ i = 1 φ ( p ) ( x i × a ) ( m o d p ) \prod\limits_{i=1}^{\varphi(p)}x_i\equiv \prod\limits_{i=1}^{\varphi(p)}(x_i\times a)\pmod p i=1φ(p)xii=1φ(p)(xi×a)(modp)
这一段的证明与费马小定理中的一段证明极其相似,所以你直接去看这篇文章就行
式子两边约掉与 p p p 互质的 ∏ i = 1 φ ( p ) x i \prod\limits_{i=1}^{\varphi(p)}x_i i=1φ(p)xi 就得到了 a φ ( p ) ≡ 1 ( m o d p ) a^{\varphi(p)}\equiv 1 \pmod p aφ(p)1(modp)

补充一点,当 p p p 取质数时, φ ( p ) = p − 1 \varphi(p)=p-1 φ(p)=p1 ,根据欧拉定理,当 a , p a,p a,p 互质时, a p − 1 ≡ 1 ( m o d p ) a^{p-1}\equiv 1\pmod p ap11(modp)
上面这个就是费马小定理。所以费马小定理是欧拉定理的特殊情况,这也是为什么它们的证明如此相似的原因。


4.扩展欧拉定理

扩展欧拉定理可用于 a , p a,p a,p 不互质的情况。
b ≥ φ ( p ) 时 , a b ≡ a b   m o d   φ ( p ) + φ ( p ) ( m o d p ) . \color{red} b\ge \varphi(p)时,a^b\equiv a^{b \bmod \varphi(p)+\varphi(p)}\pmod p. bφ(p)ababmodφ(p)+φ(p)(modp).

证明在这里
注意 b < φ ( p ) b<\varphi(p) b<φ(p) 时不能使用扩展欧拉定理


5.后记

P 5091   【 模 板 】 欧 拉 定 理 \rm P5091\ 【模板】欧拉定理 P5091  (注意这个是拓展欧拉定理)
P 2158   [ S D O I 2008 ] 仪 仗 队 \rm P2158\ [SDOI2008]仪仗队 P2158 [SDOI2008]
这两道题还是比较裸的,自己去切吧~

这篇博文的撰写参考了很多资料,在这里无法一一列出,但依然表示十分感谢。
如果您发现了一些错误,最好上洛谷私信我的号( U 38785   o r   U 93465 \rm U38785\ or\ U93465 U38785 or U93465),将会在1天内回复。在优快云反馈只能保证30天内回复,在其它场合反馈只保证365天内回复

代码的话仅供参考,早期作品写得还是比较烂的。。你管一个月前叫早期?


6.例题

2020   /   3   /   17 2020~/~3~/~17 2020 / 3 / 17 新增板块

例题:洛谷P2568 GCD
题意:求 ∑ p ∈ p r i m e ∑ i = 1 n ∑ j = 1 n [ ( i , j ) = p ] \sum\limits_{p\in \rm{prime}}\sum\limits_{i=1}^n\sum\limits_{j=1}^n[(i,j)=p] pprimei=1nj=1n[(i,j)=p]

这个变形也算比较套路的,所以放个例题示范一下操作方法
我们知道 p p p 的枚举是不可避免的,所以我们先把它放在一边

首先套路式地把gcd变成互质
∑ i = 1 n / p ∑ j = 1 n / p [ ( i , j ) = 1 ] \sum\limits_{i=1}^{n/p}\sum\limits_{j=1}^{n/p}[(i,j)=1] i=1n/pj=1n/p[(i,j)=1]/表示整除)
可以将它变形为 ( ∑ i = 1 n / p ( 2 ∑ j = 1 i [ ( i , j ) = 1 ] ) ) − 1 \left(\sum\limits_{i=1}^{n/p}\left(2\sum\limits_{j=1}^i[(i,j)=1]\right)\right)-1 (i=1n/p(2j=1i[(i,j)=1]))1
-1是因为 i = j i=j i=j 时有重复枚举,发现这时只有 i = j = 1 i=j=1 i=j=1 时它们互质,因此答案只需-1
发现里面的求和式已经符合欧拉函数的定义了
那么最后一步把式子变成 ( 2 ∑ i = 1 n / p φ ( i ) ) − 1 \left(2\sum\limits_{i=1}^{n/p}\varphi(i)\right)-1 (2i=1n/pφ(i))1
我们可以先预处理出 φ \varphi φ 的前缀和,然后就能实现 Θ ( 1 ) \Theta(1) Θ(1) 计算
外面再套个枚举 p p p 的循环就行了
时间复杂度瓶颈其实在预处理上 为 Θ ( n ) \Theta(n) Θ(n)

代码对式子又有一些小改动 不过不影响大致思路

#include<cstdio>
const int N=10000010;
int n,t,cnt,p[500000],v[N],phi[N]; long long S,s[N];
int main() {
	scanf("%d",&n); phi[1]=s[1]=1;
	for (int i=2; i<=n; ++i) {
		v[i]||(p[++cnt]=i,phi[i]=i-1);
		for (int j=1; j<=cnt&&1ll*p[j]*i<=n; ++j) {
			v[t=p[j]*i]=1;
			if (i%p[j]) phi[t]=phi[i]*(p[j]-1);
			else { phi[t]=phi[i]*p[j]; break; }
		}
		s[i]=s[i-1]+phi[i];
	}
	for (int i=1; i<=cnt; ++i) S+=s[n/p[i]];
	printf("%lld\n",(S<<1)-cnt);
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值