数论·欧拉函数

文章目录

  • 欧拉函数
    • 互质(Coprime)
    • [欧拉函数(Euler's Totient Function)](#欧拉函数(Euler's Totient Function))
    • 欧拉函数的计算公式
    • [试除法(定义法)求欧拉函数:1个数- O ( log ⁡ n ) − O ( n ) O(\log n)-O(\sqrt{n}) O(logn)−O(n )](#试除法(定义法)求欧拉函数:1个数- O ( log ⁡ n ) − O ( n ) O(\log n)-O(\sqrt{n}) O(logn)−O(n ))
    • [线性筛法求欧拉函数:n个数- O ( n ) O(n) O(n)](#线性筛法求欧拉函数:n个数- O ( n ) O(n) O(n))

欧拉函数

互质(Coprime)

若两个整数 a , b a, b a,b 满足它们的最大公约数为 1 ,即
gcd ⁡ ( a , b ) = 1 \gcd(a,b)=1 gcd(a,b)=1

则称 a a a 与 b b b 互质 (或称互素)。

等价表述: a a a 与 b b b 没有任何大于 1 的公共因子。

欧拉函数(Euler's Totient Function)

欧拉函数 φ ( n ) \varphi(n) φ(n) 定义为:
在 1 1 1 到 n n n 中与 n n n 互质的正整数的个数。


φ ( n ) = ∣ { , k ∈ Z + ∣ 1 ≤ k ≤ n , gcd ⁡ ( k , n ) = 1 , } ∣ \varphi(n) = \left| \{, k \in \mathbb{Z}^+ \mid 1 \le k \le n,\ \gcd(k,n)=1 ,\} \right| φ(n)= {,k∈Z+∣1≤k≤n, gcd(k,n)=1,}

欧拉函数的计算公式

设正整数 n n n 的质因数分解为
n = p 1 k 1 p 2 k 2 ⋯ p m k m n = p_1^{k_1} p_2^{k_2} \cdots p_m^{k_m} n=p1k1p2k2⋯pmkm

其中 p i p_i pi 为互不相同的质数 ,则
φ ( n ) = n ( 1 − 1 p 1 ) ( 1 − 1 p 2 ) ⋯ ( 1 − 1 p m ) \varphi(n) = n \left(1 - \frac{1}{p_1}\right)\left(1 - \frac{1}{p_2}\right)\cdots\left(1 - \frac{1}{p_m}\right) φ(n)=n(1−p11)(1−p21)⋯(1−pm1)

证明思路

  • 先删去能被p1倍数的
  • 删去p1和p2倍数的
  • 删去p1、p2和p3倍数的
  • 因此类推,使用容斥原理避免重复删除

证明过程

可以用"从 1 1 1 到 n n n 中,删去所有与 n n n 不互质的数"这个思路,用容斥原理做一个很自然的证明。


n = p 1 k 1 p 2 k 2 ⋯ p m k m n=p_1^{k_1}p_2^{k_2}\cdots p_m^{k_m} n=p1k1p2k2⋯pmkm

其中 p 1 , p 2 , ... , p m p_1,p_2,\dots,p_m p1,p2,...,pm 是 n n n 的全部不同质因子。

欧拉函数 φ ( n ) \varphi(n) φ(n) 表示在 1 , 2 , ... , n 1,2,\dots,n 1,2,...,n 中,与 n n n 互质的正整数个数。

因此,我们只要统计:在 1 1 1 到 n n n 中,有多少个数 不被任何一个 p i p_i pi 整除


首先看全集
1 , 2 , ... , n {1,2,\dots,n} 1,2,...,n

一共有 n n n 个数。

对于每个质因子 p i p_i pi,设
A i = 1 ≤ k ≤ n : p i ∣ k A_i={1\leq k\leq n:\ p_i\mid k} Ai=1≤k≤n: pi∣k

即 A i A_i Ai 表示"能被 p i p_i pi 整除的数"的集合。

那么,与 n n n 不互质的数,恰好就是落在并集
A 1 ∪ A 2 ∪ ⋯ ∪ A m A_1\cup A_2\cup\cdots\cup A_m A1∪A2∪⋯∪Am

中的那些数。

所以
φ ( n ) = n − ∣ A 1 ∪ A 2 ∪ ⋯ ∪ A m ∣ \varphi(n)=n-\left|A_1\cup A_2\cup\cdots\cup A_m\right| φ(n)=n−∣A1∪A2∪⋯∪Am∣


接下来用容斥原理计算这个并集的大小。

因为 p i ∣ n p_i\mid n pi∣n,所以在 1 1 1 到 n n n 中,能被 p i p_i pi 整除的数有
∣ A i ∣ = n p i |A_i|=\frac{n}{p_i} ∣Ai∣=pin

同理,同时被 p i , p j p_i,p_j pi,pj 整除的数,就是被 p i p j p_ip_j pipj 整除的数,因此有
∣ A i ∩ A j ∣ = n p i p j |A_i\cap A_j|=\frac{n}{p_ip_j} ∣Ai∩Aj∣=pipjn

类似地,
∣ A i 1 ∩ A i 2 ∩ ⋯ ∩ A i r ∣ = n p i 1 p i 2 ⋯ p i r |A_{i_1}\cap A_{i_2}\cap\cdots\cap A_{i_r}| =\frac{n}{p_{i_1}p_{i_2}\cdots p_{i_r}} ∣Ai1∩Ai2∩⋯∩Air∣=pi1pi2⋯pirn

于是由容斥原理,

∣ A 1 ∪ ⋯ ∪ A m ∣ = ∑ i n p i − ∑ i < j n p i p j + ∑ i < j < k n p i p j p k − ⋯ + ( − 1 ) m + 1 n p 1 p 2 ⋯ p m |A_1\cup\cdots\cup A_m|=\sum_{i}\frac{n}{p_i} -\sum_{i<j}\frac{n}{p_ip_j} +\sum_{i<j<k}\frac{n}{p_ip_jp_k} -\cdots +(-1)^{m+1}\frac{n}{p_1p_2\cdots p_m} ∣A1∪⋯∪Am∣=i∑pin−i<j∑pipjn+i<j<k∑pipjpkn−⋯+(−1)m+1p1p2⋯pmn

因此

φ ( n ) = n − ∣ A 1 ∪ ⋯ ∪ A m ∣ \varphi(n)=n-\left|A_1\cup\cdots\cup A_m\right| φ(n)=n−∣A1∪⋯∪Am∣

就变成
φ ( n ) = n ( 1 − ∑ i 1 p i + ∑ i < j 1 p i p j − ∑ i < j < k 1 p i p j p k + ⋯ + ( − 1 ) m 1 p 1 p 2 ⋯ p m ) \varphi(n)= n\left( 1-\sum_i\frac{1}{p_i} +\sum_{i<j}\frac{1}{p_ip_j} -\sum_{i<j<k}\frac{1}{p_ip_jp_k} +\cdots +(-1)^m\frac{1}{p_1p_2\cdots p_m} \right) φ(n)=n 1−i∑pi1+i<j∑pipj1−i<j<k∑pipjpk1+⋯+(−1)mp1p2⋯pm1

最后注意到,括号里的式子正好就是下面乘积展开后的结果:
( 1 − 1 p 1 ) ( 1 − 1 p 2 ) ⋯ ( 1 − 1 p m ) \left(1-\frac{1}{p_1}\right)\left(1-\frac{1}{p_2}\right)\cdots\left(1-\frac{1}{p_m}\right) (1−p11)(1−p21)⋯(1−pm1)

所以得到
φ ( n ) = n ( 1 − 1 p 1 ) ( 1 − 1 p 2 ) ⋯ ( 1 − 1 p m ) \varphi(n)=n\left(1-\frac{1}{p_1}\right)\left(1-\frac{1}{p_2}\right)\cdots\left(1-\frac{1}{p_m}\right) φ(n)=n(1−p11)(1−p21)⋯(1−pm1)

这就是所要证明的公式。

试除法(定义法)求欧拉函数:1个数- O ( log ⁡ n ) − O ( n ) O(\log n)-O(\sqrt{n}) O(logn)−O(n )

873. 欧拉函数

实现

  • 素因子分解+定义
  • 防止溢出的技巧,先除后乘:(1-1/p)=(p-1)/p=/p*(p-1)
cpp 复制代码
void solve() {
	cin >> n;

	for (int i = 1; i <= n; i++) {
		int a;
		cin >> a;
		int res = a;
		for (int j = 2; j <= a / j; j++) {
			if (a % j == 0) {
				while (a % j == 0) {
					a /= j;
				}
				res = res / j *(j-1);
			}
		}
		if (a > 1) {
			res = res / a * (a - 1);
		}
		cout << res << endl;
	}
}

线性筛法求欧拉函数:n个数- O ( n ) O(n) O(n)

874. 筛法求欧拉函数

实现

  • 引入phi数组,phi[i]表示i的欧拉函数值
  • 注意:素数p的欧拉函数值为p-1,一定要记得赋值!一定要记得赋值!一定要记得赋值!
  • 如果i % prime == 0:则i已经i包含prime这个素因子 (素因子的次数不影响欧拉函数的值),所以根据欧拉的计算公式,只需要补齐prime即可(N=prime*i)
  • 如果i % prime != 0,则i不包含prime这个素因子,因此需要补齐prime和(1-1/prime),化简得到就是prime-1.
cpp 复制代码
void solve() {
	cin >> n;
	for (int i = 2; i <= n; i++) {
		if (isprimes[i]) {
			phi[i] = i - 1;
			primes.push_back(i);
		}
		for (auto prime : primes) {
			if (prime > n / i)continue;// subscript out of range
			isprimes[prime * i] = 0;
			if (i % prime == 0) {
				phi[i * prime] = phi[i] * prime;
				break;
			}
			else {
				phi[i * prime] = phi[i] * (prime - 1);
			}
		}
	}
	ll res = 0;
	for (int i = 1; i <= n; i++) {
		res += (ll)phi[i];
	}
	cout << res;
}
相关推荐
2501_945424801 小时前
C++编译期矩阵运算
开发语言·c++·算法
2301_815482931 小时前
C++中的类型标签分发
开发语言·c++·算法
xushichao19892 小时前
代码生成优化技术
开发语言·c++·算法
炽烈小老头2 小时前
【每天学习一点算法 2026/03/22】前 K 个高频元素
学习·算法
2401_873204652 小时前
模板编译期循环展开
开发语言·c++·算法
木心月转码ing2 小时前
Hot100-Day51-TT70爬楼梯
算法
NAGNIP2 小时前
一文搞懂经典的优化算法都有哪些?
算法
CoovallyAIHub2 小时前
2.5GB 塞进浏览器:Mistral 开源实时语音识别,延迟不到半秒
深度学习·算法·计算机视觉
会编程的土豆2 小时前
C++中的 lower_bound 和 upper_bound:一篇讲清楚
java·数据结构·算法