Hàm nhân tính và Sàng tuyến tính
Hàm nhân tính thỏa với . Sàng tuyến tính tính mọi giá trị hàm nhân tính đến trong .
Các hàm nhân tính quan trọng
| Hàm | Ký hiệu | Định nghĩa | Ví dụ |
|---|---|---|---|
| Phi Euler | Số nguyên tố cùng nhau với trong | ||
| Möbius | nếu tích SNT phân biệt, 0 nếu có | ||
| Số ước | Số ước dương của | ||
| Tổng ước | Tổng ước dương của | ||
| Hàm đơn vị | — | ||
| Hàm hằng | với mọi | — |
Tính theo phân tích thừa số :
- nếu tất cả , ngược lại
Sàng tuyến tính —
Sàng Eratosthenes chuẩn là . Sàng tuyến tính đảm bảo mỗi số hợp bị loại đúng 1 lần:
const int MAXN = 1e7 + 5;
int phi[MAXN], mu[MAXN], lp[MAXN]; // lp[i] = smallest prime factor
vector<int> primes;
bool is_composite[MAXN];
void linear_sieve(int n) {
phi[1] = mu[1] = 1;
for (int i = 2; i <= n; i++) {
if (!is_composite[i]) {
primes.push_back(i);
lp[i] = i;
phi[i] = i - 1; // i nguyên tố: phi = i-1
mu[i] = -1; // i nguyên tố: mu = -1
}
for (int j = 0; j < (int)primes.size() && (long long)i * primes[j] <= n; j++) {
int p = primes[j];
is_composite[i * p] = true;
lp[i * p] = p;
if (i % p == 0) {
// p là ước nguyên tố nhỏ nhất của i
phi[i * p] = phi[i] * p;
mu[i * p] = 0; // i*p có p^2 => mu = 0
break;
} else {
phi[i * p] = phi[i] * (p - 1);
mu[i * p] = -mu[i];
}
}
}
}
Tích Dirichlet và Nghịch đảo Möbius
Tích Dirichlet:
Quan hệ quan trọng: tương đương (inversion):
Ví dụ: (tức là ).
Nghịch đảo Möbius trên tập hợp (SOS)
// Tính g từ f bằng Möbius inversion
// f[i] = sum_{j: i|j, j<=n} g[j] => g[i] = sum_{j: i|j} mu[j/i] * f[j]
vector<long long> mobius_inversion(vector<long long>& f, int n) {
vector<long long> g(n+1, 0);
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j += i)
g[i] += mu[j/i] * f[j];
return g;
}
Ứng dụng: Đếm cặp GCD
Đếm số cặp với có :
// Đếm cặp (i,j), 1<=i<j<=n, gcd(i,j)=1
long long count_coprime_pairs(int n) {
long long ans = 0;
for (int d = 1; d <= n; d++) {
long long cnt = n / d;
ans += mu[d] * cnt * (cnt - 1) / 2;
}
return ans;
}
Ứng dụng: Tổng phi Euler
bằng sàng: tính trực tiếp . Dùng công thức để tính :
// Tính sum phi(i) cho i=1..n trong O(sqrt(n)) bằng Dirichlet hyperbola
// Dùng f(n) = n*(n+1)/2, f = phi * 1, inversion: phi = f * mu
Khi nào dùng?
- Bài toán đếm với điều kiện GCD — dùng Möbius inversion.
- Tính hàm nhân tính đến lớn — dùng sàng tuyến tính.
- trong bài toán modular inverse, Euler's theorem ().
Bình luận