欧拉函数
概念讲解
什么是欧拉函数?
欧拉函数 φ(n) 表示小于等于 n 且与 n 互质的正整数的个数。
性质
- φ(1) = 1
- φ(p) = p - 1(p 是质数)
- φ(p^k) = p^k - p^(k-1)
- φ(nm) = φ(n)φ(m)(n, m 互质)
计算方法
单个数的欧拉函数
123456789101112131415161718int euler(int n) {
int result = n;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
result -= result / i;
while (n % i == 0) {
n /= i;
}
}
}
if (n > 1) {
result -= result / n;
}
return result;
}线性筛求欧拉函数
1234567891011121314151617181920212223242526const int N = 1000005;
int phi[N];
int primes[N], cnt;
bool isPrime[N];
void eulerSieve(int n) {
phi[1] = 1;
for (int i = 2; i <= n; i++) {
if (!isPrime[i]) {
primes[cnt++] = i;
phi[i] = i - 1;
}
for (int j = 0; j < cnt && i * primes[j] <= n; j++) {
isPrime[i * primes[j]] = true;
if (i % primes[j] == 0) {
phi[i * primes[j]] = phi[i] * primes[j];
break;
} else {
phi[i * primes[j]] = phi[i] * (primes[j] - 1);
}
}
}
}欧拉定理
定理
如果 gcd(a, n) = 1,则 a^φ(n) ≡ 1 (mod n)。
应用
求逆元:a 的逆元是 a^(φ(n)-1)。
考点分析
初赛考查方式
- 选择题: 欧拉函数的概念
- 程序阅读: 理解欧拉函数计算
- 编程题: 欧拉函数应用
常见题型
- 欧拉函数计算
- 互质数计数
- 欧拉定理应用
例题精讲
例题 1:欧拉函数
题目: 求 φ(n)。
解答:
123456789101112131415161718192021222324252627282930#include <iostream>
using namespace std;
int euler(int n) {
int result = n;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
result -= result / i;
while (n % i == 0) {
n /= i;
}
}
}
if (n > 1) {
result -= result / n;
}
return result;
}
int main() {
int n;
cin >> n;
cout << euler(n) << endl;
return 0;
}练习题
- 洛谷 P2158 仪仗队
查看答案
思路:欧拉函数,求与 n 互质的数的个数。
123456789101112131415161718192021222324252627282930313233343536373839#include <iostream>
using namespace std;
int euler(int n) {
int result = n;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
result -= result / i;
while (n % i == 0) {
n /= i;
}
}
}
if (n > 1) {
result -= result / n;
}
return result;
}
int main() {
int n;
cin >> n;
if (n == 1) {
cout << 0 << endl;
return 0;
}
long long ans = 0;
for (int i = 2; i < n; i++) {
ans += euler(i);
}
cout << ans * 2 + 3 << endl;
return 0;
}- 洛谷 P2568 GCD
查看答案
思路:欧拉函数 + 前缀和。
123456789101112131415161718192021222324252627282930313233343536373839404142434445#include <iostream>
using namespace std;
const int N = 10000005;
int phi[N], prime[N], cnt;
bool isPrime[N];
void init() {
phi[1] = 1;
for (int i = 2; i < N; i++) {
if (!isPrime[i]) {
prime[cnt++] = i;
phi[i] = i - 1;
}
for (int j = 0; j < cnt && i * prime[j] < N; j++) {
isPrime[i * prime[j]] = true;
if (i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
}
int main() {
init();
int n;
cin >> n;
long long prefix[n + 1];
prefix[0] = 0;
for (int i = 1; i <= n; i++) {
prefix[i] = prefix[i - 1] + phi[i];
}
long long ans = 0;
for (int d = 1; d <= n; d++) {
ans += 2 * prefix[n / d] - 1;
}
cout << ans << endl;
return 0;
}- 洛谷 P1390 公约数的和
查看答案
思路:欧拉函数 + 前缀和。
12345678910111213141516171819202122232425262728293031323334353637383940414243#include <iostream>
using namespace std;
const int N = 2000005;
int phi[N], prime[N], cnt;
bool isPrime[N];
void init() {
phi[1] = 1;
for (int i = 2; i < N; i++) {
if (!isPrime[i]) {
prime[cnt++] = i;
phi[i] = i - 1;
}
for (int j = 0; j < cnt && i * prime[j] < N; j++) {
isPrime[i * prime[j]] = true;
if (i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
}
int main() {
init();
int n;
cin >> n;
long long ans = 0;
for (int d = 1; d <= n; d++) {
long long sum = 0;
for (int i = d; i <= n; i += d) {
sum += phi[i / d];
}
ans += d * sum;
}
cout << ans << endl;
return 0;
}易错点
⚠️ 注意:
- 欧拉函数是积性函数
- 欧拉定理要求 gcd(a, n) = 1
- 线性筛可以同时求欧拉函数
- 欧拉函数与逆元有关