无极之地
WUJI
无极之地。记录所思所见,慢慢写下去。
欧拉定理与费马小定理
世界时钟 北京 --:--:-- 东京 --:--:-- UTC --:--:-- 伦敦 --:--:-- 纽约 --:--:-- 在 1 , 2 , … , n 1,2,\dots,n 1 , 2 , … , n 里,有多少个数和 n n n 互素?这个计数记作 φ ( n ) \varphi(n) φ ( n ) ,叫欧拉函数。它看起来只是在数个数,真正要抓住的却是三件事:定义在数什么、为什么互素模数上可以拆开乘、以及公式 φ ( n ) = n ∏ p ∣ n ( 1 − 1 / p ) \varphi(n)=n\prod_{p\mid n}(1-1/p) φ ( n ) = n 从哪来。
∏ p ∣ n
(
1
−
1/ p )
定义:就是在数互素 φ ( n ) = # { a : 1 ≤ a ≤ n , gcd ( a , n ) = 1 } \varphi(n)=\#\{a:1\le a\le n,\ \gcd(a,n)=1\} φ ( n ) = # { a : 1 ≤ a ≤ n , g cd( a , n ) = 1 } 也就是 { 1 , 2 , … , n } \{1,2,\dots,n\} { 1 , 2 , … , n } 中与 n n n 互素的个数。约定 φ ( 1 ) = 1 \varphi(1)=1 φ ( 1 ) = 1 ,因为 gcd ( 1 , 1 ) = 1 \gcd(1,1)=1 g cd( 1 , 1 ) 。
例如 n = 10 n=10 n = 10 :和 10 10 10 互素的是 1 , 3 , 7 , 9 1,3,7,9 1 , 3 , 7 , 9 ,所以 φ ( 10 ) = 4 \varphi(10)=4 φ ( 10 ) = 4 。n = 7 n=7 n 是素数,前面六个都和它互素,所以 。一般地,素数 满足 。
这个定义本身就是「与互素个数的关系」:φ ( n ) \varphi(n) φ ( n ) 不是后补的抽象符号,它就是那个个数。后面的积性和公式,都是为了不用一个一个去试 gcd \gcd g cd 。
区间取 1 1 1 到 n n n 还是 0 0 0 到 n − 1 n-1 n − 1 ,答案一样。0 0 0 与 n n n 不互素(n > 1 n>1 n > 时),而 本身也不与 互素,两边各少一个,计数不变。 时两边都只剩 这一个。所以写 也常见,尤其在谈剩余类的时候。
换一个群论的说法,意思完全一样。模 n n n 的剩余类里,有乘法逆元的恰好是那些与 n n n 互素的类:裴蜀定理保证 gcd ( a , n ) = 1 \gcd(a,n)=1 g cd( a , n ) = 1 当且仅当存在 x x x 使 a x ≡ 1 ( m o d n ) ax\equiv 1\pmod n a x ≡ 。这些可逆类组成乘法群 ,阶就是 。所以「互素个数」和「可逆剩余类个数」是同一件事。
还可以问一个略宽的问题:在 1 1 1 到 n n n 里,与 n n n 的最大公因数恰好是 d d d 的有多少个?令 a = d b a=d b a = d b ,条件变成 gcd ( b , n / d ) = 1 \gcd(b,n/d)=1 g cd( b , n 且 ,于是恰好 个。特别地 就回到 。这个分组后面证明 时还要用。
几个立刻能算的特例
φ ( 1 ) = 1 \varphi(1)=1 φ ( 1 ) = 1
p p p 为素数:φ ( p ) = p − 1 \varphi(p)=p-1 φ ( p ) = p − 1
p k p^k p 为素幂:在 到 里,不互素的恰好是 的倍数,有 个,所以
φ ( p k ) = p k − p k − 1 = p k − 1 ( p − 1 ) = p k ( 1 − 1 p ) \varphi(p^k)=p^k-p^{k-1}=p^{k-1}(p-1)=p^k\bigl(1-\tfrac{1}{p}\bigr) φ ( p k ) = p k − p k n = 9 = 3 2 n=9=3^2 n = 9 = 3 2 :不互素的是 3 , 6 , 9 3,6,9 3 , 6 , 9 ,剩下 1 , 2 , 4 , 5 , 7 , 8 1,2,4,5,7,8 1 , 2 , 4 , 5 , 7 , ,共 个,对上 。
n = 8 = 2 3 n=8=2^3 n = 8 = 2 3 :和 8 8 8 互素的只能是奇数 1 , 3 , 5 , 7 1,3,5,7 1 , 3 , 5 , 7 ,共 4 4 4 个,对上 8 ( 1 。
素幂之所以好算,是因为「不互素」只有一种原因:被唯一的那个 p p p 整除。合数一旦有两个不同素因子,不互素的方式就交叉了,必须用积性或容斥把交叉减干净。
积性:互素就可以拆 数论里说一个函数 f f f 是积性的,意思是:只要 gcd ( m , n ) = 1 \gcd(m,n)=1 g cd( m , n ) = 1 ,就有
f ( m n ) = f ( m ) f ( n ) f(mn)=f(m)f(n) f ( mn ) = f ( m ) f ( n ) 若对任意 m , n m,n m , n (不要求互素)都成立,叫完全积性。φ \varphi φ 是积性的,但不是完全积性:φ ( 4 ) = 2 \varphi(4)=2 φ ( 4 ) = 2 ,而 φ ( 2 ) φ ( 2 ) = 1 \varphi(2)\varphi(2)=1 φ ( 2 ) φ ( 2 ) = 1 ,对不上。
为什么互素时能拆?中国剩余定理给一个双射。gcd ( m , n ) = 1 \gcd(m,n)=1 g cd( m , n ) = 1 时,映射
a m o d m n ⟼ ( a m o d m , a m o d n ) a\bmod mn\ \longmapsto\ (a\bmod m,\ a\bmod n) a mod mn ⟼ ( a mod m , a mod n ) 是一一对应。左边与 m n mn mn 互素,当且仅当右边分别与 m m m 、n n n 互素:因为素数 p p p 若整除 m n mn mn 又整除 a a a ,则 p p p 整除 m m 或 ,于是对应分量也不互素。反过来也对。于是互素剩余类的个数相乘:
φ ( m n ) = φ ( m ) φ ( n ) \varphi(mn)=\varphi(m)\varphi(n) φ ( mn ) = φ ( m ) φ ( n ) 不必把 CRT 的构造全写一遍。只要接受「模 m n mn mn 的一个数,同时被模 m m m 和模 n n n 的一对余数唯一确定」,互素条件就会按分量拆开。
用 m = 3 m=3 m = 3 、n = 4 n=4 n = 4 看一眼。模 12 12 12 与 12 12 12 互素的是 1 , 5 , 7 , 11 1,5,7,11 1 , 5 , 7 , 11 ,共 4 4 个。模 互素的有 个,模 互素的有 个, 。配对是
1 ↦ ( 1 , 1 ) , 5 ↦ ( 2 , 1 ) , 7 ↦ ( 1 , 3 ) , 11 ↦ ( 2 , 3 ) \begin{aligned}
1 &\mapsto (1,1),\quad
5 &\mapsto (2,1),\\
7 &\mapsto (1,3),\quad
11 &\mapsto (2,3)
\end{aligned} 1 7 ↦ ( 1 , 1 ) , 5 右边恰好穷尽「模 3 3 3 互素」× \times × 「模 4 4 4 互素」的四对。
若不用 CRT 的语言,也可以直接数。设 gcd ( m , n ) = 1 \gcd(m,n)=1 g cd( m , n ) = 1 。在 1 1 1 到 m n mn mn 里取 a a a ,把它写成 a = q n + r a=qn+r a = q n + ,其中 。要 ,必须同时 和 。前者只依赖于 ,所以 必须落在与 互素的 种余数上。对固定的这种 ,再看 时 模 的变化:因为 模 可逆,这 个数恰好跑遍所有模 剩余类,其中与 互素的有 个。于是总数是 。
这条计数和 CRT 是同一件事,只是把双射拆成「先定模 n n n 的余数,再数模 m m m 还剩多少选择」。
公式从素因子分解来 n = ∏ i p i k i n=\prod_i p_i^{k_i} n = i ∏ p i k i φ ( n ) = ∏ i φ ( p i k i ) = ∏ i p i k i ( 1 − 1 p i ) = n ∏ p ∣ n ( 1 − 1 p ) \varphi(n)=\prod_i \varphi(p_i^{k_i})=\prod_i p_i^{k_i}\bigl(1-\tfrac{1}{p_i}\bigr)=n\prod_{p\mid n}\bigl(1-\tfrac{1}{p}\bigr) φ ( n ) = i ∏ φ ( p 这就是标准公式。乘积只跑过互异 的素因子,指数 k i k_i k i 已经收进前面的 n n n 里。写成
φ ( n ) = n ∏ p ∣ n p − 1 p \varphi(n)=n\prod_{p\mid n}\frac{p-1}{p} φ ( n ) = n p ∣ n ∏ p p − 1 同一回事,手算时往往更好用:先把 n n n 对每个素因子各约掉一份,再乘上 p − 1 p-1 p − 1 。等价地:
φ ( n ) = ∏ i p i k i − 1 ( p i − 1 ) \varphi(n)=\prod_i p_i^{k_i-1}(p_i-1) φ ( n ) = i ∏ p i k i − 1 n = p k n=p^k n = p k 时公式退化成上一节的素幂情形,所以局部和全局是对齐的。
公式里真正依赖的是 n n n 的素因子集合 ,不是指数。因此 φ ( 12 ) = φ ( 4 ⋅ 3 ) \varphi(12)=\varphi(4\cdot 3) φ ( 12 ) = φ ( 4 ⋅ 3 ) 和 φ ( 6 ⋅ 2 ) \varphi(6\cdot 2) φ ( 6 ⋅ 2 ) 的拆法不同,但 φ ( p k ) / p k = 1 − 1 / p \varphi(p^k)/p^k=1-1/p 对所有 都一样: 。比值 等于 ,只看 被哪些素数除得尽。
这也解释了为什么分解时不必记住每个指数对公式「多贡献了什么」:指数已经在前面的 n n n 里,乘积部分每个 p p p 只出现一次。手算最稳的顺序是:写出标准分解,抄下互异素数,再从 n n n 出发依次乘 ( p − 1 ) / p (p-1)/p ( p − 1 ) / p 。
另一种证明:容斥 不一定走积性。在 1 1 1 到 n n n 里先假定全都算上,有 n n n 个。再丢掉被某个素因子 p p p 整除的,每个 p p p 挖掉 n / p n/p n / p 个。两个素因子 p , q p,q p , q 同时整除的被减了两次,要加回 。这就是容斥:
φ ( n ) = n − ∑ p ∣ n n p + ∑ p < q n p q − ⋯ = n ∏ p ∣ n ( 1 − 1 p ) \varphi(n)=n-\sum_{p\mid n}\frac{n}{p}+\sum_{p<q}\frac{n}{pq}-\cdots=n\prod_{p\mid n}\bigl(1-\tfrac{1}{p}\bigr) φ ( n ) = n − p ∣ n ∑ p 和前面同一条公式。积性证明解释「为什么能拆成局部」,容斥证明解释「为什么每个素因子贡献一个 1 − 1 / p 1-1/p 1 − 1/ p 」。
把 n = 30 = 2 ⋅ 3 ⋅ 5 n=30=2\cdot 3\cdot 5 n = 30 = 2 ⋅ 3 ⋅ 5 展开一次就清楚了。1 1 1 到 30 30 30 共 30 30 30 个数。被 2 2 2 整除的 15 个,被 整除的 个,被 整除的 个;两两相交: 有 个, 有 个, 有 个;三个都整除的只有 自己, 个。于是
φ ( 30 ) = 30 − 15 − 10 − 6 + 5 + 3 + 2 − 1 = 8 \varphi(30)=30-15-10-6+5+3+2-1=8 φ ( 30 ) = 30 − 15 − 10 − 6 + 5 + 3 + 2 − 1 = 8 公式给出 30 ⋅ 1 / 2 ⋅ 2 / 3 ⋅ 4 / 5 = 8 30\cdot 1/2\cdot 2/3\cdot 4/5=8 30 ⋅ 1/2 ⋅ 2/3 ⋅ 4/5 = 8 。列出互素的:1 , 7 , 11 , 13 , 17 , 19 , 23 , 29 1,7,11,13,17,19,23,29 1 , 7 , 11 , 13 , 17 , 19 , 23 , 。容斥每一步都对应「至少被这些素因子整除」,最后剩下的就是一个素因子都不沾的那些。
∑ d ∣ n φ ( d ) = n \sum_{d\mid n}\varphi(d)=n d ∣ n ∑ φ ( d ) = n 原因是把 { 1 , 2 , … , n } \{1,2,\dots,n\} { 1 , 2 , … , n } 按 gcd ( a , n ) = d \gcd(a,n)=d g cd( a , n ) = d 分组。每组里 a = d ⋅ b a=d\cdot b a = d ⋅ b ,且 ,所以该组恰好有 个元素。令 ,得到右边是所有 的和,等于 。
例如 n = 12 n=12 n = 12 的因数是 1 , 2 , 3 , 4 , 6 , 12 1,2,3,4,6,12 1 , 2 , 3 , 4 , 6 , 12 ,
φ ( 1 ) + φ ( 2 ) + φ ( 3 ) + φ ( 4 ) + φ ( 6 ) + φ ( 12 ) = 1 + 1 + 2 + 2 + 2 + 4 = 12 \varphi(1)+\varphi(2)+\varphi(3)+\varphi(4)+\varphi(6)+\varphi(12)=1+1+2+2+2+4=12 φ ( 1 ) + φ ( 2 ) + φ ( 3 ) + φ ( 4 ) + φ ( 6 ) + φ ( 12 这个式子可以用莫比乌斯反演推回 φ ( n ) = ∑ d ∣ n μ ( d ) n / d \varphi(n)=\sum_{d\mid n}\mu(d)\,n/d φ ( n ) = ∑ d ∣ n μ ( d ) n / d ,再展开 μ \mu μ ,又得到同一条乘积公式。三条路走到同一处,说明公式不是凑出来的。
恒等式也可以当验算:算出一串 φ ( d ) \varphi(d) φ ( d ) 之后,对某个 n n n 把所有因数上的值加起来,应当恰好等于 n n n 。手算 φ ( 36 ) = 12 \varphi(36)=12 φ ( 36 ) = 12 之后,可以再加 φ ( 1 ) + φ ( 2 ) + φ ( 3 ) + φ ( 4 ) + φ ( 6 ) + φ ( 9 ) + φ ( 12 ) ,应当得到 。加错了多半是某个素幂或积性用错了。
手算例子
例一:先分解再套公式 算 φ ( 36 ) \varphi(36) φ ( 36 ) 。36 = 2 2 ⋅ 3 2 36=2^2\cdot 3^2 36 = 2 2 ⋅ 3 2 ,
φ ( 36 ) = 36 ( 1 − 1 2 ) ( 1 − 1 3 ) = 36 ⋅ 1 2 ⋅ 2 3 = 12 \varphi(36)=36\bigl(1-\tfrac12\bigr)\bigl(1-\tfrac13\bigr)=36\cdot\tfrac12\cdot\tfrac23=12 φ ( 36 ) = 36 ( 1 − 2 1 ) ( 1 或 φ ( 36 ) = φ ( 4 ) φ ( 9 ) = 2 ⋅ 6 = 12 \varphi(36)=\varphi(4)\varphi(9)=2\cdot 6=12 φ ( 36 ) = φ ( 4 ) φ ( 9 ) = 2 ⋅ 6 = 12 。列出 1 1 1 到 36 36 36 中与 36 36 互素的: ,正好 个。
例二:素幂 φ ( 32 ) = φ ( 2 5 ) = 2 4 = 16 \varphi(32)=\varphi(2^5)=2^4=16 φ ( 32 ) = φ ( 2 5 ) = 2 4 = 16 。和 32 32 32 互素就是奇数,1 1 1 到 有 个奇数。
例三:三个不同素数 φ ( 105 ) \varphi(105) φ ( 105 ) 。105 = 3 ⋅ 5 ⋅ 7 105=3\cdot 5\cdot 7 105 = 3 ⋅ 5 ⋅ 7 ,
φ ( 105 ) = 105 ⋅ 2 3 ⋅ 4 5 ⋅ 6 7 = 48 \varphi(105)=105\cdot\tfrac23\cdot\tfrac45\cdot\tfrac67=48 φ ( 105 ) = 105 ⋅ 3 2 ⋅ 5 逐步算:105 × 2 / 3 = 70 105\times 2/3=70 105 × 2/3 = 70 ,70 × 4 / 5 = 56 70\times 4/5=56 70 × 4/5 = 56 ,56 × 6 / 7 = 48 56\times 6/7=48 56 × 6/7 = 48 。也可以先写成 。中间带着 连乘时,每一步都整除,不容易乘错。
例四:不是完全积性 比较 φ ( 12 ) \varphi(12) φ ( 12 ) 和 φ ( 2 ) φ ( 6 ) \varphi(2)\varphi(6) φ ( 2 ) φ ( 6 ) 。12 = 2 2 ⋅ 3 12=2^2\cdot 3 12 = 2 2 ⋅ 3 ,φ ( 12 ) = 12 ⋅ 1 / 2 ⋅ 2 / 3 。 , ,乘积是 ,对不上。因为 和 不互素,积性用不上。
若硬拆 12 = 3 ⋅ 4 12=3\cdot 4 12 = 3 ⋅ 4 ,两边互素,就恢复 φ ( 3 ) φ ( 4 ) = 2 ⋅ 2 = 4 \varphi(3)\varphi(4)=2\cdot 2=4 φ ( 3 ) φ ( 4 ) = 2 ⋅ 2 = 4 。
例五:用定义核对一个合数 n = 15 = 3 ⋅ 5 n=15=3\cdot 5 n = 15 = 3 ⋅ 5 。按公式 φ ( 15 ) = 15 ⋅ 2 / 3 ⋅ 4 / 5 = 8 \varphi(15)=15\cdot 2/3\cdot 4/5=8 φ ( 15 ) = 15 ⋅ 2/3 ⋅ 4/5 = 8 。按定义,1 1 到 里与 互素的是 ,共 个。被 或 整除的都被排除了,正好是容斥在小数上的样子。
例六:较大但仍可手算 φ ( 360 ) \varphi(360) φ ( 360 ) 。360 = 2 3 ⋅ 3 2 ⋅ 5 360=2^3\cdot 3^2\cdot 5 360 = 2 3 ⋅ 3 2 ⋅ 5 ,
φ ( 360 ) = 360 ⋅ 1 2 ⋅ 2 3 ⋅ 4 5 = 96 \varphi(360)=360\cdot\tfrac12\cdot\tfrac23\cdot\tfrac45=96 φ ( 360 ) = 360 ⋅ 2 1 ⋅ 3 逐步:360 / 2 = 180 360/2=180 360/2 = 180 ,180 ⋅ 2 / 3 = 120 180\cdot 2/3=120 180 ⋅ 2/3 = 120 ,120 ⋅ 4 / 5 = 96 120\cdot 4/5=96 120 ⋅ 4/5 = 96 。用另一写法:φ ( 8 ) φ ( 9 ) φ ( 5 ) = 4 。两种路径对得上,通常说明分解没有漏素因子。
若题目给的是「1 1 1 到 360 360 360 中与 360 360 360 互素的数有多少」,不要去枚举,直接算 φ ( 360 ) \varphi(360) φ ( 360 ) 。这就是定义与公式的分工:定义告诉你在数什么,公式告诉你怎么数。
一份可直接用的实现 计算 φ ( n ) \varphi(n) φ ( n ) 的关键是试除分解。试到 n \sqrt{n} n 即可;每碰到一个素因子 p p p ,先把 n n n 里的 除尽,同时用 贡献因子 。
def euler_phi ( n : int ) -> int :
""" 返回 φ(n)。n 必须为正整数。 """
if n <= 0 :
raise ValueError ( " n 必须为正整数 " )
result = n
x = n
i = 2
while i * i <= x :
if x % i == 0 :
while x % i == 0 :
x //= i
result -= result // i
i += 1
跑一下,两列应完全一致,并和前面的手算对上:1 , 6 , 4 , 6 , 4 , 4 , 8 , 16 , 12 , 48 1,6,4,6,4,4,8,16,12,48 1 , 6 , 4 , 6 , 4 , 4 , 8 , 16 , 12 , 48 。euler_phi 是 O ( n ) O(\sqrt n) O ( n ,单次查询足够。需要很多 时,改成线性筛,让每个素数走过自己的倍数,按公式乘上一次 。
def phi_sieve ( N : int ) -> list [ int ]:
""" 返回数组 phi,使 phi[k] = φ(k),下标到 N。 """
phi = list ( range ( N + 1 ))
for i in range ( 2 , N + 1 ):
if phi [ i ] == i : # i 是素数
for j in range ( i , N + 1 , i ):
phi [ j ] -= phi [ j ] // i
return phi 筛法的意思是:每个素数 p p p 走过它的倍数 j j j ,给 j j j 乘上一次 ( 1 − 1 / p ) (1-1/p) ( 1 − 1/ p ) 。每个合数只会被自己的各个互异素因子各改一次,正好对应公式里的乘积。时间 O ( N log log N ) O(N\log\log N) O ( N log log ,和埃氏筛同级。
若只要前 N N N 项,筛比反复试除快一个数量级以上;若只要单个很大的 n n n ,试除仍然更合适。
线性筛还可以在分解的同时递推。记最小素因子 l p f ( n ) = p \mathrm{lpf}(n)=p lpf ( n ) = p ,写出 n = p k m n=p^k m n = p k m 且 p ∤ m p\nmid m p ∤ m ,则
φ ( n ) = φ ( p k ) φ ( m ) = p k − 1 ( p − 1 ) φ ( m ) \varphi(n)=\varphi(p^k)\varphi(m)=p^{k-1}(p-1)\varphi(m) φ ( n ) = φ ( p k ) φ ( m ) = p k − 1 ( p − 实现时常见两种转移:若 p 2 ∣ n p^2\mid n p 2 ∣ n ,则 φ ( n ) = φ ( n / p ) ⋅ p \varphi(n)=\varphi(n/p)\cdot p φ ( n ) = φ ( n / p ) ⋅ p ;否则 φ ( n ) = φ ( n / p ) ⋅ ( p − 1 ) \varphi(n)=\varphi(n/p)\cdot(p-1) 。前者对应多乘一个已经出现过的素因子,比值 不变,所以 只按 放大;后者是第一次碰到 ,要补上 。和单点试除是同一套公式,只是把分解摊到筛的过程里。
写代码时容易踩的坑 n = 1 n=1 n = 1 要单独成立。循环从 2 2 2 开始试除时,x x x 一开始就是 1 1 1 ,不会进任何素因子分支,result 保持 1 1 1 ,这是对的。不要特判成 0 0 0 。
更新用 result -= result // p,不要写成先乘 p − 1 p-1 p − 1 再除 p p p 却把顺序弄反。整数除法必须整除;先减再除能保证每一步都是整数,因为此时 p p p 整除当前的 result。
只对每个互异素因子更新一次。内层 while 把 p p p 除尽,外层才做减法。如果每个 p p p 的幂次都减一次,就会把 φ ( p k ) \varphi(p^k) φ ( p k ) 算成 p k ( 1 − 1 / p ) k p^k(1-1/p)^k p k ( 1 − 。
试除上界是变化中的 x x x ,不是原始的 n n n 。把小因子剥掉之后 x x x 变小,循环可以更早停。最后若 x > 1 x>1 x > 1 ,它本身是一个大于 n 原 \sqrt{n_{\text{原}}} n 原 的素因子,还要再贡献一次。
φ ( n ) \varphi(n) φ ( n ) 对 n ≥ 3 n\ge 3 n ≥ 3 一定是偶数。这可以当断言:算完若得到奇数且 n > 2 n>2 n > 2 ,多半是漏了一个素因子。原因是:奇数素因子贡献偶数 p − 1 p-1 p − 1 ;若 n n n 是 的幂且至少是 ,则 也是偶数。
不要对不互素的因子用积性。euler_phi(m) * euler_phi(n) 只有在 gcd ( m , n ) = 1 \gcd(m,n)=1 g cd( m , n ) = 1 时才等于 φ ( m n ) \varphi(mn) φ ( mn ) 。测例里放一组 φ ( 12 ) \varphi(12) φ ( 12 ) 对 φ ( 2 ) φ ( 6 ) \varphi(2)\varphi(6) φ ( 2 ) φ ( 6 ) ,能把这个错觉挡住。
φ ( n ) \varphi(n) φ ( n ) 本身可以比 n n n 小很多。n n n 的小素因子越多,∏ ( 1 − 1 / p ) \prod(1-1/p) ∏ ( 1 − 1/ p ) 越小。例如 φ ( 30 ) / 30 = 8 / 30 ≈ 0.267 \varphi(30)/30=8/30\approx 0.267 φ ( 30 ) /30 ,而素数处 接近 。写随机测试时不要默认「答案大概是 的一半」;偶数已经至少打了 ,再乘几个小素数会继续往下掉。
和欧拉定理的边界 欧拉定理说:若 gcd ( a , n ) = 1 \gcd(a,n)=1 g cd( a , n ) = 1 ,则
a φ ( n ) ≡ 1 ( m o d n ) a^{\varphi(n)}\equiv 1\pmod n a φ ( n ) ≡ 1 ( mod n ) 所以 φ ( n ) \varphi(n) φ ( n ) 也是群 ( Z / n Z ) × (\mathbb{Z}/n\mathbb{Z})^\times ( Z / n Z ) × 的阶。模逆、RSA 的指数、把费马小定理从素数模扩到一般模,都会用到它。费马小定理是特例:n = p n=p n = p 素数时 φ ( p ) = p − 1 \varphi(p)=p-1 φ ( p ) ,于是 。
这些是 φ \varphi φ 的去处,不是定义本身。先把「数互素个数」和乘积公式算准,再用到定理不迟。定理要成立,前提恰好是 a a a 落在那 φ ( n ) \varphi(n) φ ( n ) 个互素类里;不互素时连逆元都没有,幂次同余要另说。
收束 φ ( n ) \varphi(n) φ ( n ) 的定义就是 1 1 1 到 n n n 里与 n n n 互素的个数。互素模数上它按 CRT 拆开,因而是积性的;落到素因子上,每个 p p p 贡献 1 − 1 / p 1-1/p 1 − 1/ p ,于是
φ ( n ) = n ∏ p ∣ n ( 1 − 1 p ) \varphi(n)=n\prod_{p\mid n}\bigl(1-\tfrac{1}{p}\bigr) φ ( n ) = n p ∣ n ∏ ( 1 − p 1 手算先分解,再连乘;代码里试除或线性筛做同一件事。不必把它看成一串要背的式子。把计数、积性和容斥对上,公式就会自己长出来。
回到开头那句问话:φ ( n ) \varphi(n) φ ( n ) 就是 1 1 1 到 n n n 里与 n n n 互素的个数。会算这个数,一次同余里「有几个可逆元」、RSA 里「模 n n n 的乘法群有多大」,才有地方落脚。公式是加速计数的工具,不是另一套定义。
=
1
=
7
φ ( p ) = p − 1 \varphi(p)=p-1 φ ( p ) = p − 1 1
{ a : 0 ≤ a < n , gcd ( a , n ) = 1 } \{a:0\le a<n,\ \gcd(a,n)=1\} { a : 0 ≤ a < n , g cd( a , n ) = 1 } 1
( mod n )
( Z / n Z ) × (\mathbb{Z}/n\mathbb{Z})^\times ( Z / n Z ) × /
d
)
=
1
1 ≤ b ≤ n / d 1\le b\le n/d 1 ≤ b ≤ n / d ∑ d ∣ n φ ( d ) = n \sum_{d\mid n}\varphi(d)=n ∑ d ∣ n φ ( d ) = n k
−
1
=
p k − 1 ( p −
1 ) =
p k ( 1 −
p 1 )
8
9 ( 1 − 1 / 3 ) = 6 9(1-1/3)=6 9 ( 1 − 1/3 ) = 6 − 1 / 2 ) = 4 8(1-1/2)=4 8 ( 1 − 1/2 ) = 4
m
4
↦ ( 1 , 3 ) , 11
↦ ( 2 , 1 ) , ↦ ( 2 , 3 )
r
gcd ( a , m n ) = 1 \gcd(a,mn)=1 g cd( a , mn ) = 1 gcd ( a , n ) = 1 \gcd(a,n)=1 g cd( a , n ) = 1 gcd ( a , m ) = 1 \gcd(a,m)=1 g cd( a , m ) = 1 q = 0 , 1 , … , m − 1 q=0,1,\dots,m-1 q = 0 , 1 , … , m − 1 φ ( m ) φ ( n ) \varphi(m)\varphi(n) φ ( m ) φ ( n ) i
k i
)
=
i ∏ p i k i ( 1 −
p i 1 ) =
n p ∣ n ∏ ( 1 −
p 1 )
(
p i
−
1 )
φ ( p k ) / p k = 1 − 1/ p
φ ( 2 ) = φ ( 4 ) / 2 = φ ( 8 ) / 4 = φ ( 16 ) / 8 = 1 / 2 \varphi(2)=\varphi(4)/2=\varphi(8)/4=\varphi(16)/8=1/2 φ ( 2 ) = φ ( 4 ) /2 = φ ( 8 ) /4 = φ ( 16 ) /8 = 1/2 ∏ p ∣ n ( 1 − 1 / p ) \prod_{p\mid n}(1-1/p) ∏ p ∣ n ( 1 − 1/ p )
n
+
p < q ∑ pq n −
⋯ =
n p ∣ n ∏ ( 1 −
p 1 )
15 15
29
gcd ( b , n / d ) = 1 \gcd(b,n/d)=1 g cd( b , n / d ) = 1
)
=
1 +
1 +
2 +
2 +
2 +
4 =
12
+ φ ( 18 ) + φ ( 36 ) \varphi(1)+\varphi(2)+\varphi(3)+\varphi(4)+\varphi(6)+\varphi(9)+\varphi(12)+\varphi(18)+\varphi(36) φ ( 1 ) + φ ( 2 ) + φ ( 3 ) + φ ( 4 ) + φ ( 6 ) + φ ( 9 ) + φ ( 12 ) + φ ( 18 ) + φ ( 36 )
−
3 1 ) =
36 ⋅
2 1 ⋅
3 2 =
12
36
1 , 5 , 7 , 11 , 13 , 17 , 19 , 23 , 25 , 29 , 31 , 35 1,5,7,11,13,17,19,23,25,29,31,35 1 , 5 , 7 , 11 , 13 , 17 , 19 , 23 , 25 , 29 , 31 , 35 32
4
⋅
7 6 =
48
( 3 − 1 ) ( 5 − 1 ) ( 7 − 1 ) = 48 (3-1)(5-1)(7-1)=48 ( 3 − 1 ) ( 5 − 1 ) ( 7 − 1 ) = 48
= 4 \varphi(12)=12\cdot 1/2\cdot 2/3=4 φ ( 12 ) = 12 ⋅ 1/2 ⋅ 2/3 = 4
1
1 , 2 , 4 , 7 , 8 , 11 , 13 , 14 1,2,4,7,8,11,13,14 1 , 2 , 4 , 7 , 8 , 11 , 13 , 14 2
⋅
5 4 =
96
⋅ 6 ⋅ 4 = 96 \varphi(8)\varphi(9)\varphi(5)=4\cdot 6\cdot 4=96 φ ( 8 ) φ ( 9 ) φ ( 5 ) = 4 ⋅ 6 ⋅ 4 = 96
p p p
result ← result − result / p \textit{result}\leftarrow\textit{result}-\textit{result}/p result ← result − result / p if
x
>
1
:
result -= result // x
return result
def phi_by_count ( n : int ) -> int :
""" 按定义枚举,用来核对小数。 """
from math import gcd
return sum ( 1 for a in range ( 1 , n + 1 ) if gcd ( a , n ) == 1 )
if __name__ == " __main__ " :
samples = ( 1 , 7 , 8 , 9 , 10 , 12 , 15 , 32 , 36 , 105 )
for n in samples :
print ( n , euler_phi ( n ), phi_by_count ( n ))
)
φ ( 1 ) , … , φ ( N ) \varphi(1),\dots,\varphi(N) φ ( 1 ) , … , φ ( N )
N
)
1
)
φ
(
m
)
φ ( n ) = φ ( n / p ) ⋅ ( p − 1 )
1/
p
) k
2 2 2
φ ( 2 k ) = 2 k − 1 \varphi(2^k)=2^{k-1} φ ( 2 k ) = 2 k − 1
=
8/30 ≈
0.267
φ ( p ) / p = 1 − 1 / p \varphi(p)/p=1-1/p φ ( p ) / p = 1 − 1/ p
=
p −
1
a p − 1 ≡ 1 ( m o d p ) a^{p-1}\equiv 1\pmod p a p − 1 ≡ 1 ( mod p )
)
欧拉函数 φ(n):定义、积性与公式 · 无极之地