欧拉函数
欧拉函数 Euler' totient function
即 φ(n),表示 1~n 中 且与n互质的数的个数 ;
通式:
φ(n) = n * ∏质数p | n (1 - 1 / p) ;
即: n = p1k1 * p2k2 * p3k3 * ...... * pmkm
φ(n) = n * (1 - 1 / p1) * (1 - 1 / p2) * (1 - 1 / p3) * ...... * (1 - 1 / pm)
特别地 :φ(1) = 1;
当 n 是质数时 φ(n) = n - 1 ;
当 n 是奇数时 φ(2n) = φ(n) ;
性质:
-
- 欧拉函数是积性函数 :若 gcd(a, b) = 1 ; 则 φ(a * b) = φ(a) * φ(b) ; 特别地 :当 n 为奇数时 φ(2n) = φ(n) ;
积性函数:对于任意互质的整数 a 和 b 有性质 ƒ(a * b) =ƒ(a) * ƒ(b) ;
完全积性函数:对于任意整数 a 和 b 有性质 ƒ(a * b) = ƒ(a) * ƒ(b) ;
积性函数的性质:
-
- n = p1a1 * p2a2 * p3a3 * ...... * pnan —— n 表示质因数的分解式 ;
- 若 ƒ 为积性函数 且 n = p1a1 * p2a2 * p3a3 * ...... * pnan ,则 ƒ(n) = ƒ(p1a1) * ƒ( p2a2) * ƒ(p3a3) * ...... *ƒ(pnan)
- 若 ƒ 为积性函数 且有 ƒ(pn) = ƒ n(p) ,则 ƒ 为完全积性函数 ;
- 特别地 : 当 n 为奇数时 ƒ(2n) = ƒ(n) ;
-
-
- n = ∑d | n φ(d) ,∑d | n φ(d) = n ;
- 对任意 n > 1 ,1 ~ n 中与 n 互质的数的和为 n * φ(n) / 2 ;
- 若 n = p k ,其中 p 是质数,那么 φ(n) = p k - p k - 1 =(p - 1) * p k - 1 ;
- 设 p 为质数,若 p | n 且 p2 | n (p2 是 n 的质数),即:n,n / p 包含相同的质因子,
则: φ(n) = φ(n / p) * p ;(φ(n) = n * ∏质数p | n (1 - 1 / p) ; φ(n / p) = (n / p) * ∏质数p | n / p (1 - 1 / p) ; 则 φ(n) / φ(n / p) = p)
-
- 设 p 为质数,若 p | n 且 p2 † n (p2 不是 n 的质数),即:p,n / p 互质,
则:φ(n) = φ(n / p) * (p - 1) ;(由积性函数 可得 φ(n) = φ(n / p) * φ(p) ;p 是质数 可得 φ(p) = p - 1)
模板:
- 求一个数的欧拉函数
根据欧拉函数的计算公式:φ(n) = n * ∏质数p | n (1 - 1 / p) ;只需要分解质因数,即可求出欧拉函数
1 int phi(int n) { 2 int ans = n; 3 for (int i = 2; i * i<= n; i++) 4 if (n % i == 0) { 5 ans = ans / i * (i - 1); 6 while (n % i == 0) n /= i; 7 } 8 if (n > 1) ans = ans / n * (n - 1); 9 return ans; 10 }
- 求2~n 中每个数的欧拉函数
- 利用埃拉托斯托尼筛法(埃氏筛法的核心是:如果 x 是合数,那么 x 的倍数也是合数;合数与质数相对,最小合数是4,1既不是合数也不是质数) 时间复杂度:O(nlogn)
1 void euler(int n) { 2 for (int i = 2; i <= n; i++) phi[i] = i; 3 for (int i = 2; i <= n; i++) 4 if (phi[i] == i) 5 for (int j = i; j <= n; j += i) 6 phi[j] = phi[j] / i * (i - 1); 7 }
-
- 利用线性筛法 时间复杂度:O(n)
由性质:
1.设 p 为质数,若 p | n 且 p2 | n (p2 是 n 的质数),即:n,n / p 包含相同的质因子,则: φ(n) = φ(n / p) * p ;
2.设 p 为质数,若 p | n 且 p2 † n (p2 不是 n 的质数),即:p,n / p 互质,则:φ(n) = φ(n / p) * (p - 1) ;
在线性筛法中,每个合数 n 只会被它的最小质因子 p 筛一次,可通过上面的两条性质 从 φ(n / p) 递推到 φ(n)
1 int v[MAX_N], prime[MAX_N], phi[MAX_N]; 2 int m; 3 void euler(int n) { 4 memset(v, 0, sizeof(v)); //标记最小质因子 5 m = 0; //质数数量 6 for (int i = 2; i <= n; i++) { 7 if (v[i] == 0) { //i是质数 8 v[i] = i; 9 prime[++m] = i; //存储质数 10 phi[i] = i - 1; 11 } 12 //给当前的数i乘上一个质因子 13 for (int j = i; j <= m; j++) { 14 if (prime[j] > v[i] || prime[j] > n / i) //i有比prime[j]更小的质因子,或者超出n的范围,停止循环 15 break; 16 v[i * prime[j]] = prime[j]; //prime[j]是合数i*prime[j]的最小质因子 17 phi[i * prime[j]] = phi[i] * (i % prime[j] ? prime[j] - 1 : prime[j]); //判断使用上面的性质1还是2 18 19 } 20 } 21 }

浙公网安备 33010602011771号