0.概述
一个函数。只有毒瘤出题人会用到它。
1.定义
φ ( n ) = ∑ x = 1 n [ gcd ( x , n ) = 1 ] \varphi(n)=\sum_{x=1}^{n}\big[\gcd(x,n)=1\big] φ(n)=x=1∑n[gcd(x,n)=1]
即,所有小于等于 n n n 的正整数,与 n n n 互质的有多少个。顺带一说,互质也可写为 a ⊥ b a\perp b a⊥b 。
2.计算
2.1.积性函数
如果
a
a
a 和
b
b
b 互质,那么
φ
(
a
b
)
=
φ
(
a
)
⋅
φ
(
b
)
\varphi(ab)=\varphi(a)\cdot \varphi(b)
φ(ab)=φ(a)⋅φ(b)
证明:发现 gcd ( x , a b ) = 1 \gcd(x,ab)=1 gcd(x,ab)=1 的充要条件是 gcd ( x , a ) = 1 ∧ gcd ( x , b ) = 1 \gcd(x,a)=1\wedge\gcd(x,b)=1 gcd(x,a)=1∧gcd(x,b)=1 。
那么设 x = k b + t ( 0 ⩽ k < a , 0 ⩽ t < b ) x=kb+t\;(0\leqslant k<a,\;0\leqslant t<b) x=kb+t(0⩽k<a,0⩽t<b),由 x ⊥ b ⇔ t ⊥ b x\perp b\Leftrightarrow t\perp b x⊥b⇔t⊥b 可知,不同的 t t t 的数量是 φ ( b ) \varphi(b) φ(b) 个。
另一方面,对于某个 t t t,肯定有 { k b + t m o d a ∣ k ∈ [ 0 , a ) } = { 0 , 1 , 2 , … , a − 1 } \{kb+t\bmod a\;|\;k\in[0,a)\}=\{0,1,2,\dots,a{\rm-}1\} {kb+tmoda∣k∈[0,a)}={0,1,2,…,a−1},所以可行的 k k k 只有 φ ( a ) \varphi(a) φ(a) 个。二者相乘就是 φ ( a b ) = φ ( a ) ⋅ φ ( b ) \varphi(ab)=\varphi(a)\cdot\varphi(b) φ(ab)=φ(a)⋅φ(b) 。
2.2.一般的计算
如果
p
p
p 是一个质数,
k
k
k 是正整数,那么
φ
(
p
k
)
=
p
k
−
1
(
p
−
1
)
\varphi(p^k)=p^{k-1}(p-1)
φ(pk)=pk−1(p−1)
证明: x ⊥ p k ⇔ x ⊥ p ⇔ x = k p ( 1 ⩽ k ⩽ p k − 1 ) x\perp p^k\Leftrightarrow x\perp p\Leftrightarrow x=kp\;(1\leqslant k\leqslant p^{k-1}) x⊥pk⇔x⊥p⇔x=kp(1⩽k⩽pk−1),故 φ ( p k ) = p k − p k − 1 \varphi(p^k)=p^k-p^{k-1} φ(pk)=pk−pk−1,证毕。
再结合 积性函数
,如果
n
n
n 的质因数分解是
n
=
p
1
t
1
p
2
t
2
p
3
t
3
…
p
m
t
m
n=p_1^{t_1}p_2^{t_2}p_3^{t_3}\dots p_m^{t_m}
n=p1t1p2t2p3t3…pmtm ,那么
φ
(
n
)
=
∏
x
=
1
m
p
x
t
x
−
1
(
p
x
−
1
)
\varphi(n)=\prod_{x=1}^{m}p_x^{t_x-1}(p_x-1)
φ(n)=x=1∏mpxtx−1(px−1)
2.3.特殊的计算
其实就是 一般的计算
变了形。
φ
(
n
)
=
n
∏
p
∣
n
(
1
−
1
p
)
\varphi(n)=n\prod_{p\mid n}\left(1-\frac{1}{p}\right)
φ(n)=np∣n∏(1−p1)
也可以理解为容斥,即考虑是否去掉某个质因数的倍数。注意这里隐式规定 p ∈ Prime p\in\text{Prime} p∈Prime 。
3.性质
3.0.积性函数
前面已经讲过 积性函数
,这里就略过。
3.1.与 n n n 的关系
还有一个很美妙的结论(使得杜教筛在
φ
\varphi
φ 上可以大显身手):
∑
d
∣
n
φ
(
d
)
=
n
\sum_{d|n}\varphi(d)=n
d∣n∑φ(d)=n
快速证明:由容斥可知 i d ∗ μ = φ id*\mu=\varphi id∗μ=φ,两边同乘 I I I 得 i d = φ ∗ I id=\varphi*I id=φ∗I,证毕。其中 ∗ * ∗ 为狄利克雷卷积。
初等证明:将 { 1 , 2 , 3 , … , n } \{1,2,3,\dots,n\} {1,2,3,…,n} 按如下规则划分: S d = { x ∣ gcd ( x , n ) = d } S_d=\{x\mid\gcd(x,n)=d\} Sd={x∣gcd(x,n)=d} 。显然 S 1 ∪ S 2 ∪ ⋯ ∪ S n = { 1 , 2 , 3 , … , n } S_1\cup S_2\cup\cdots\cup S_n=\{1,2,3,\dots,n\} S1∪S2∪⋯∪Sn={1,2,3,…,n} 。
对于任意 x ∈ S d x\in S_d x∈Sd,可以写成 x = k d ( 1 ⩽ k ⩽ n d x=kd\;(1\leqslant k\leqslant\frac{n}{d} x=kd(1⩽k⩽dn 但不一定取遍 ) ) ) 。
由定义, gcd ( x , n ) = gcd ( k d , n ) = d ⇒ gcd ( k , n d ) = 1 \gcd(x,n)=\gcd(kd,n)=d\Rightarrow\gcd(k,\frac{n}{d})=1 gcd(x,n)=gcd(kd,n)=d⇒gcd(k,dn)=1 。
这样一来, ∣ S d ∣ = φ ( n d ) |S_d|=\varphi(\frac{n}{d}) ∣Sd∣=φ(dn) 。于是 n = ∑ d ∣ n ∣ S d ∣ = ∑ d ∣ n φ ( n d ) n=\sum_{d|n}|S_d|=\sum_{d|n}\varphi(\frac{n}{d}) n=∑d∣n∣Sd∣=∑d∣nφ(dn),得证。
3.2.与莫比乌斯挂钩
∑ d ∣ n μ ( d ) d = φ ( n ) n \sum_{d|n}\frac{\mu(d)}{d}=\frac{\varphi(n)}{n} d∣n∑dμ(d)=nφ(n)
比较显然且用处不大,此处从略。
3.3.“偶性”
2 ∣ φ ( n ) ( n ⩾ 3 ) 2\mid\varphi(n)\quad(n\geqslant 3) 2∣φ(n)(n⩾3)
证明:如果
n
n
n 中含有任意一个奇素因数
p
p
p ,那么根据 一般的计算
,可知
2
∣
(
p
−
1
)
∣
φ
(
n
)
2\mid(p-1)\mid\varphi(n)
2∣(p−1)∣φ(n) 。
而不包含奇素因数的数只有 1 1 1 和 2 2 2 。
3.4.“收敛” 速度快
接下来的这一点,是很多题复杂度的保障:如果 2 ∣ n 2\mid n 2∣n ,那么 φ ( n ) ⩽ n 2 \varphi(n)\leqslant \frac{n}{2} φ(n)⩽2n 。
证明:
n
n
n 中含有
p
=
2
p=2
p=2 这一质因子。根据 特殊的计算
,
φ
(
n
)
⩽
n
(
1
−
1
p
)
=
n
2
\varphi(n)\leqslant n(1-\frac{1}{p})=\frac{n}{2}
φ(n)⩽n(1−p1)=2n 。
再结合 偶性
可知,每次令
n
i
=
φ
(
n
i
−
1
)
n_i=\varphi(n_{i-1})
ni=φ(ni−1),那么
i
⩾
⌈
log
2
n
⌉
i\geqslant\lceil\log_2n\rceil
i⩾⌈log2n⌉ 即可让
n
i
=
1
n_i=1
ni=1 。
3.5.欧拉降幂
我另开了一篇博客写这个……
4.代码实现
4.1.求单点值
直接用 一般的计算
,暴搜质因数分解,复杂度
O
(
n
)
\mathcal O(\sqrt n)
O(n) 。
int getPhi(int n){
int res = 1;
for(int x=2; x<=n/x; ++x){
if(n%x) continue;
n /= x, res *= (x-1);
while(n%x == 0)
n /= x, res *= x;
}
if(n != 1) res *= (n-1);
return res;
}
我个人更喜欢写法二,感觉常数小一点。
long long __phi(long long n){
long long res = n;
for(int i=2; i<=n/i; ++i)
if(n%i == 0){
res -= res/i, n /= i;
while(n%i == 0) n /= i;
}
if(n != 1) res -= res/n;
return res;
}
4.2.奇怪法求单点值
int getPhi(int n){
vector<int> ys; // 质因数
while(n != 1){
d = findDivisor(n); // 找到一个质因数
ys.push_back(d);
while(n%d == 0) n /= d;
}
sort(ys.begin(),ys.end());
n = ys.size(); int res = n;
for(int S=1; S<(1<<n); ++S){
int sgn = 1, cnt = n;
// 是质因子集合S中每一个质因子的倍数的个数
for(int i=0; i<n; ++i)
if(S>>i&1){
sgn = -sgn;
cnt /= ys[i];
}
res += sgn*cnt;
}
return res;
}
好处是什么呢?——可以求 ∑ x = 1 n [ gcd ( x , m ) = 1 ] \sum_{x=1}^{n}[\gcd(x,m)=1] ∑x=1n[gcd(x,m)=1] 。只需要稍稍作一点改动。
4.3.奇怪法
int getCoprime(int n,int m){
vector<int> ys; // 质因数
while(m != 1){
d = findDivisor(m); // 找到一个质因数
ys.push_back(d);
while(m%d == 0) m /= d;
}
sort(ys.begin(),ys.end());
m = ys.size(); int res = n;
for(int S=1; S<(1<<m); ++S){
int sgn = 1, cnt = n;
// 是质因子集合S中每一个质因子的倍数的个数
for(int i=0; i<n; ++i)
if(S>>i&1)
sgn = -sgn, cnt /= ys[i];
res += sgn*cnt;
}
return res;
}
4.4.所有因数的单点值
能够做到 n \sqrt n n 的复杂度——也就是说,均摊 O ( 1 ) \mathcal O(1) O(1) 。
首先线性筛求出 x ∈ [ 1 , n ] x\in[1,\sqrt n] x∈[1,n] 的 φ ( x ) \varphi(x) φ(x),然后 O ( n ) \mathcal O(\sqrt n) O(n) 的求出 φ ( n ) \varphi(n) φ(n) 。接下来要做的,就是研究 φ ( x ) , φ ( n x ) , φ ( n ) \varphi(x),\;\varphi(\frac{n}{x}),\;\varphi(n) φ(x),φ(xn),φ(n) 的关系。
观察 特殊的计算
中的右半部分,也就是
∏
p
∣
n
(
1
−
1
p
)
\prod_{p|n}(1-\frac{1}{p})
∏p∣n(1−p1) ,将其记为
λ
(
n
)
\lambda(n)
λ(n) 。于是就有
n
λ
(
n
)
=
φ
(
n
)
n\lambda(n)=\varphi(n)
nλ(n)=φ(n) 。
考虑这样一个恒等式:记
d
=
gcd
(
x
,
n
x
)
d=\gcd(x,\frac{n}{x})
d=gcd(x,xn) ,那么
λ
(
x
)
⋅
λ
(
n
x
)
=
λ
(
n
)
λ
(
d
)
\lambda(x)\cdot\lambda\left(\frac{n}{x}\right)=\lambda(n)\lambda(d)
λ(x)⋅λ(xn)=λ(n)λ(d)
证明:如果 p ∣ d p\mid d p∣d,在两边都会被计算两次;如果 p ∤ n p\nmid n p∤n,那么两边都一次也不会计算;其他的情况,两边都只计算一次。证毕。
把两边同时乘一个
n
n
n 可以得到:
x
λ
(
x
)
⋅
n
x
⋅
λ
(
n
x
)
=
n
λ
(
n
)
λ
(
d
)
⇒
φ
(
x
)
φ
(
n
x
)
=
φ
(
n
)
φ
(
d
)
d
⇒
φ
(
n
x
)
=
φ
(
n
)
φ
(
d
)
d
φ
(
x
)
x\lambda(x)\cdot \frac{n}{x}\cdot \lambda\Big(\frac{n}{x}\Big)=n\lambda(n)\lambda(d)\\ \Rightarrow \varphi(x)\varphi\Big(\frac{n}{x}\Big)=\varphi(n)\frac{\varphi(d)}{d}\\ \Rightarrow\varphi\Big(\frac{n}{x}\Big)=\frac{\varphi(n)\varphi(d)}{d\varphi(x)}
xλ(x)⋅xn⋅λ(xn)=nλ(n)λ(d)⇒φ(x)φ(xn)=φ(n)dφ(d)⇒φ(xn)=dφ(x)φ(n)φ(d)
更形式化地,
φ
(
a
)
φ
(
b
)
=
φ
(
a
b
)
φ
[
gcd
(
a
,
b
)
]
gcd
(
a
,
b
)
\varphi(a)\varphi(b)=\varphi(ab)\frac{\varphi[\gcd(a,b)]}{\gcd(a,b)}
φ(a)φ(b)=φ(ab)gcd(a,b)φ[gcd(a,b)]
可以发现,这是自洽的——在
gcd
(
a
,
b
)
=
1
\gcd(a,b)=1
gcd(a,b)=1 的情况下,自然满足 积性函数
咯。
求 gcd ( x , n x ) \gcd(x,{n\over x}) gcd(x,xn) 怎样避免 O ( log n ) \mathcal O(\log n) O(logn) 辗转相除呢?一种方法是,由于 x ⩽ n x\leqslant\sqrt{n} x⩽n,我们可以用快速 gcd \gcd gcd 算法。这样不费脑子。
另一种方法是,求出 x ∈ [ 1 , n ] x\in[1,\sqrt{n}] x∈[1,n] 的质因数表示。具体来说,存储最小质因数与对应的次数,以及除以它得到的值(即记录 x = p k v x=p^kv x=pkv 其中 p p p 为最小质因子且 p ⊥ v p\perp v p⊥v )。我们已经用 O ( n ) \mathcal O(\sqrt{n}) O(n) 搜出了 n n n 的质因数分解(用 unordered map \texttt{unordered map} unordered map 桶计数就行,因为不同 p p p 的数量甚至低于 log n \log n logn,可视为常数),那么 gcd ( x , n x ) \gcd(x,{n\over x}) gcd(x,xn) 中 p p p 的指数易得,最后乘上 gcd ( v , n v ) ( v = x p k ) \gcd(v,{n\over v})\;(v={x\over p^k}) gcd(v,vn)(v=pkx) 即可。
5.例题
Naive Great Common Divisor \text{Naive Great Common Divisor} Naive Great Common Divisor
电磁看题。应该算比较常规的方法。
The Luckiest Number \text{The Luckiest Number} The Luckiest Number
点此跳转。用欧拉公式解决关于 x x x 的方程 a x ≡ 1 ( m o d b ) a^x\equiv 1\pmod b ax≡1(modb) 。
POAIBE \text{POAIBE} POAIBE
电磁跳转。 p.s. \text{p.s.} p.s. 这个名字是缩写。
杜教筛求 φ \varphi φ 的前缀和
我们已经知道了 φ ∗ I = i d \varphi*I=id φ∗I=id ,直接用即可。
放公式:令
S
n
=
∑
i
=
1
n
φ
(
i
)
S_n=\sum_{i=1}^{n}\varphi(i)
Sn=∑i=1nφ(i) ,一定有
S
n
=
n
(
n
+
1
)
2
−
∑
d
=
1
n
S
(
⌊
n
d
⌋
)
S_n=\frac{n(n+1)}{2}-\sum_{d=1}^{n}S(\lfloor\frac{n}{d}\rfloor)
Sn=2n(n+1)−d=1∑nS(⌊dn⌋)
map<int,long long> wk; /* WK(freopen) or2 */
long long djs(int n){
if(n < SqrtN)
return phi[n]; /* 线性筛中得到的结果 */
if(wk.count(n)) return wk[n]; /* 记忆化 */
long long res = 1ll*n*(n+1)>>1;
for(int l=1,r; l<=n; l=r){
r = n/(n/l)+1; /* 整除分块 */
res -= (r-l)*djs(n/l);
}
return wk[n] = res;
}
复杂度是
O
(
n
2
3
)
\mathcal O(n^{2\over 3})
O(n32) 的。计算过程我放在别的博客的不显眼之处了,不知道也罢。