Prerequisites: number-theoretic block decomposition, Dirichlet convolution
Möbius inversion is an important topic in number theory. For some functions , if it is difficult to compute their values directly but easy to compute their multiple sums or divisor sums , Möbius inversion can simplify the computation and yield the values of .
Möbius Function
The Möbius function is defined by
Specifically, suppose the positive integer has prime factorization , where are primes and are positive integers. The three cases correspond to:
- ;
- If there exists with , meaning that some prime factor occurs more than once, then ;
- Otherwise, for every , , meaning every prime factor occurs exactly once, , where is the number of distinct prime factors.
Properties
It is easy to verify from the definition that the Möbius function is multiplicative but not completely multiplicative. More importantly, it satisfies the following identity:
Property
For a positive integer ,
Here is the Iverson bracket.
Using Dirichlet convolution, this expression can be written as . In other words, the Möbius function is the Dirichlet inverse of the constant function .
A very common application of this property is:
This converts the coprimality condition into a sum involving the Möbius function, making further derivations convenient.
Computing the Function
For a single , compute the value of the Möbius function using its prime factorization. For example, when is not too large, it can be computed in time, yielding .
Reference Implementation
C++
int mu(int n) {
int res = 1;
for (int i = 2; i * i <= n; ++i) {
if (n % i == 0) {
n /= i;
// Check if square-free.
if (n % i == 0) return 0;
res = -res;
}
}
// The remaining factor must be prime.
if (n > 1) res = -res;
return res;
}
Python
def mu(n):
res = 1
i = 2
while i * i <= n:
if n % i == 0:
n //= i
# Check if square-free
if n % i == 0:
return 0
res = -res
i += 1
# The remaining factor must be prime
if n > 1:
res = -res
return res
For the first positive integers, precompute using its multiplicativity and a linear sieve in time.
Reference Implementation
C++
std::vector<int> get_mu(int n) {
std::vector<int> mu(n + 1), primes;
std::vector<bool> not_prime(n + 1);
primes.reserve(n);
mu[1] = 1;
for (int x = 2; x <= n; ++x) {
if (!not_prime[x]) {
primes.push_back(x);
mu[x] = -1;
}
for (int p : primes) {
if (x * p > n) break;
not_prime[x * p] = true;
if (x % p == 0) {
mu[x * p] = 0;
break;
} else {
mu[x * p] = -mu[x];
}
}
}
return mu;
}
Python
def get_mu(n):
mu = [0] * (n + 1)
primes = []
not_prime = [False] * (n + 1)
mu[1] = 1
for x in range(2, n + 1):
if not not_prime[x]:
primes.append(x)
mu[x] = -1
for p in primes:
if x * p > n:
break
not_prime[x * p] = True
if x % p == 0:
mu[x * p] = 0
break
else:
mu[x * p] = -mu[x]
return mu
Möbius Inversion
The most important application of the Möbius function is Möbius inversion.
Möbius Inversion
Let be two arithmetic functions. Then
Proof 1
Direct verification gives:
The key steps are exchanging the order of summation and observing that is equivalent to . The penultimate equality sums the Möbius function over the divisors of , so it equals . This expression is nonzero only when ; in that case, it is not , and the result is .
Proof 2
Using Dirichlet convolution, the proposition is equivalent to
Using , convolve both sides of the equality on the left with ; this gives
Möbius inversion is a powerful transformation tool for sums of arithmetic functions involving divisibility relations.
Examples
-
The Euler totient function satisfies , equivalently . Inverting it gives , equivalently
-
The divisor function , equivalently . Inverting it gives , equivalently
-
The number of distinct prime factors , equivalently , where is the indicator of the prime set . Inverting it gives , equivalently
-
Consider the arithmetic function satisfying , denoted by . It is the Möbius inversion of the logarithm and is also called the von Mangoldt function:
Proof of the expression for
For a prime power , there is
For , clearly . For other composite ,
By the properties of the Möbius function, the coefficient of the term is . For the latter term, factor further into primes. For any prime , consider the coefficient of ; it is:
Thus every composite with more than one prime factor satisfies .
Extensions
Besides the basic form above, Möbius inversion has several common extensions. First consider its multiple-sum form.
Extension 1
Let be two arithmetic functions. Then
Proof
Direct verification gives:
This derivation is completely dual to that of the basic form.
Möbius inversion is not limited to addition; in fact, it holds for operations in any Abelian group. For example, it has the following multiplicative form:
Extension 2
Let be two arithmetic functions. Then
Proof
Direct verification gives:
Here is the Knuth arrow. Comparing this proof with the basic one, the only differences are replacing addition by multiplication and multiplication by exponentiation.
From the perspective of Dirichlet convolution, Möbius inversion uses only the fact that the Möbius function is the Dirichlet inverse of the constant function. It is natural that analogous inversion relations also hold for a general Dirichlet inverse.
Extension 3
Let be arithmetic functions, and suppose is the Dirichlet inverse of , namely
Then
Proof
Direct verification gives:
Compared with the proof of the basic form, only the penultimate equality needs to be replaced by the definition of the Dirichlet inverse.
Corollary
Let be arithmetic functions, and let be completely multiplicative. Then
Proof
By the properties of Dirichlet convolution, the Dirichlet inverse of a completely multiplicative function is .
Finally, Möbius inversion extends to complex-valued functions on , not only arithmetic functions. The basic form is the special case in which the complex-valued functions vanish at all nonintegral points.
Extension 4
Let and be complex-valued functions on . Then
Proof
Extend and to the region , where they satisfy . Then the proposition is equivalent to:
All these sums range over .
Direct verification gives:
To obtain the second equality, set .
Corollary
Let be arithmetic functions. Then
Proof
It suffices to take and .
These extensions can be combined with one another to obtain more complicated inversion relations.
Dirichlet Prefix Sums
Prerequisite: prefix sums and differences
Consider the basic Möbius inversion relation:
In the left-hand equality, the value at is the sum of the values over its divisors. If is interpreted as appearing before , then can be viewed as a kind of prefix sum of . Thus, in domestic programming contests, the process in which is used to obtain is also called a Dirichlet prefix sum, and the reverse process is called a Dirichlet difference. These methods mostly arise when precomputing the values of an arithmetic function at the first points.
Next, consider computing Dirichlet prefix sums. If every prime is treated as a dimension, this is a high-dimensional prefix sum. Recall the dimension-by-dimension prefix-sum algorithm: traverse the dimensions one by one and add each position's value to its successor along that dimension. For arithmetic functions, this means traversing primes in increasing order and adding the function value at to . This is the same traversal order as the Sieve of Eratosthenes. Therefore, this algorithm computes the Dirichlet prefix sum in time for a sequence of length . Similarly, a dimension-by-dimension difference computes the Dirichlet difference in the same time complexity.
Reference Implementation
Dirichlet Prefix Sum
std::vector<int> dirichlet_presum(const std::vector<int>& g) {
int n = g.size() - 1;
std::vector<int> f(g);
std::vector<bool> vis(n + 1);
for (int x = 2; x <= n; ++x) {
if (vis[x]) continue;
for (int y = 1, xy = x; xy <= n; ++y, xy += x) {
vis[xy] = true;
f[xy] += f[y];
}
}
return f;
}
Dirichlet Difference
std::vector<int> dirichlet_diff(const std::vector<int>& f) {
int n = f.size() - 1;
std::vector<int> g(f);
std::vector<int> vis(n + 1);
for (int x = 2; x <= n; ++x) {
if (vis[x]) continue;
for (int y = n / x, xy = x * y; y; --y, xy -= x) {
vis[xy] = true;
g[xy] -= g[y];
}
}
return g;
}
This method can be extended to multiple sums (Extension 1), the multiplicative form (Extension 2), and replacing the constant function with a completely multiplicative function (the corollary of Extension 3), among others.
Examples
This section demonstrates applications of Möbius inversion and common transformation techniques. We begin with an example illustrating the basic technique for handling greatest-common-divisor conditions in a summation.
Solution
By inclusion–exclusion, the original expression can be split into blocks, each having the form
For expressions of this kind, the standard derivation is: factor out common divisors, apply properties of the Möbius function, and exchange the order of summation.
Since can only be multiples of , factor this out first—equivalently substitute and , obtaining:
By the Möbius-function identity,
Substituting this and exchanging the order of summation gives:
The benefit is that, with fixed, the terms involving and separate and can be summed independently. Next, since
Therefore,
After precomputing with a linear sieve and its prefix sums, number-theoretic block decomposition solves the problem. The total time complexity is , where is the upper bound for , and is the number of test cases.
Reference Code
#include <algorithm>
#include <iostream>
using namespace std;
constexpr int N = 50000;
int mu[N + 5], p[N + 5];
bool flg[N + 5];
void init() {
int tot = 0;
mu[1] = 1;
for (int i = 2; i <= N; ++i) {
if (!flg[i]) {
p[++tot] = i;
mu[i] = -1;
}
for (int j = 1; j <= tot && i * p[j] <= N; ++j) {
flg[i * p[j]] = true;
if (i % p[j] == 0) {
mu[i * p[j]] = 0;
break;
}
mu[i * p[j]] = -mu[i];
}
}
for (int i = 1; i <= N; ++i) mu[i] += mu[i - 1];
}
int solve(int n, int m) {
int res = 0;
for (int i = 1, j; i <= min(n, m); i = j + 1) {
j = min(n / (n / i), m / (m / i));
res += (mu[j] - mu[i - 1]) * (n / i) * (m / i); // Formula derived above
}
return res;
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int T, a, b, c, d, k;
init(); // Precompute the mu array
cin >> T;
for (int i = 1; i <= T; i++) {
cin >> a >> b >> c >> d >> k;
// By inclusion–exclusion, subtract the count in 1<=x<=b&&1<=y<=c-1 from the count in 1<=x<=b&&1<=y<=d, and
// add the count in 1<=x<=a-1&&1<=y<=c-1 to the count in 1<=x<=a-1&&1<=y<=d,
// obtaining the count in a<=x<=b&&c<=y<=d.
// If this step is unclear, draw a coordinate diagram to understand it
cout << solve(b / k, d / k) - solve(b / k, (c - 1) / k) -
solve((a - 1) / k, d / k) + solve((a - 1) / k, (c - 1) / k)
<< '\n';
}
return 0;
}
The next two examples demonstrate enumerating common divisors and using a sieve to compute values of general multiplicative functions.
SPOJ LCMSUM
test cases. For each case, compute:
Constraints: .
Solution 1
The problem gives a least common multiple, but a greatest common divisor is often easier to handle. First transform it:
Factor out and enumerate the greatest common divisor :
For the inner sum, this is the standard greatest-common-divisor case; repeating the usual procedure gives:
Again, the sum over separates from the other terms and can be handled independently. The final sum is an arithmetic-progression sum (take ):
This yields:
After enumerating common divisors, double sums of this form are common. Use the standard method: set the product to a new variable , then exchange the order of summation again. Since is equivalent to , the expression becomes:
Let ; then the expression has the form:
Since is multiplicative, its convolution with the constant function , namely , is also multiplicative. Although the sum above has the form of a Dirichlet convolution, is not multiplicative, so the whole sum is not multiplicative. However, is a polynomial, hence a linear combination of completely multiplicative functions. Thus,
Both terms (without their coefficients) are multiplicative and can be precomputed directly with a linear sieve (or the inner function can be sieved first and then preprocessed with a Dirichlet prefix sum in time). Specifically, let
To derive their expressions, it suffices to determine their values at prime powers. For a prime and positive exponent ,
In particular, is the constant function, while
This is easy to solve with a linear sieve. After precomputing , a query can be answered using in time. The total time complexity is , where is the upper bound for and is the number of test cases.
The reference implementation derives the linear-sieve part further using the special form of this problem; this is not necessary. Using only the values at prime powers, preprocessing can still be completed in time. The derivation is given in Solution 2.
Solution 2
For this problem, there is a more flexible approach. Solution 1 shows that
Instead of continuing Möbius inversion here, observe that the following sum is actually the sum of integers not exceeding and coprime to it. For , the integers not exceeding that are coprime to it occur in pairs: and are both coprime to , so
For ,
Therefore, the original expression can be written as
Since is the Dirichlet convolution of the multiplicative function with the constant function , it is multiplicative and can be precomputed with a linear sieve. It remains to determine its values at prime powers. For a prime and positive exponent ,
This agrees with the result derived in Solution 1. The total time complexity remains .
Finally, the expression of this multiplicative function permits a further optimization of the linear sieve. For a prime ,
For a general , the key to the linear sieve is computing . This splits into two cases. When , multiplicativity of gives
Otherwise, when , write with ; then
Direct verification shows that this expression also holds when . Therefore,
Substituting into the equation above gives
This simplifies the linear-sieve computation. The derivation is not necessary: for a multiplicative function without special properties, directly completes the linear sieve.
Reference Code
#include <iostream>
constexpr int N = 1000000;
int tot, p[N + 5];
long long g[N + 5];
bool flg[N + 5]; // Marker array
void solve() {
g[1] = 1;
for (int i = 2; i <= N; ++i) {
if (!flg[i]) {
p[++tot] = i;
g[i] = (long long)1 * i * (i - 1) + 1;
}
for (int j = 1; j <= tot && i * p[j] <= N; ++j) {
flg[i * p[j]] = true;
if (i % p[j] == 0) {
g[i * p[j]] =
g[i] + (g[i] - g[i / p[j]]) * p[j] * p[j]; // Formula derived above
break;
}
g[i * p[j]] = g[i] * g[p[j]];
}
}
}
using std::cin;
using std::cout;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int T, n;
solve(); // Precompute the g array
cin >> T;
for (int i = 1; i <= T; ++i) {
cin >> n;
cout << (g[n] + 1) * n / 2 << '\n';
}
return 0;
}
Solution
Ignore the modulus during the derivation. Let
Again convert the least common multiple to a greatest common divisor, enumerate the divisor, and apply the standard procedure to obtain
Again, the sums over and separate. First compute these inner sums by extracting a factor (take ); then
Here is the arithmetic-progression sum, and the final equality uses a property of the floor function. The other sum is symmetric. Substituting into the previous expression gives
As before, expressions enumerating common divisors usually require enumerating the product and exchanging the order of summation again:
Let
This is the product of the multiplicative function and the multiplicative function , so it is multiplicative. Precompute it and its prefix sums with a linear sieve, then use number-theoretic block decomposition to compute . The total time complexity is .
Reference Code
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
constexpr int M = 20101009;
int n, m;
std::cin >> n >> m;
if (n > m) std::swap(n, m);
std::vector<int> f(n + 1), vis(n + 1), prime;
prime.reserve(n);
f[1] = 1;
for (int x = 2; x <= n; ++x) {
if (!vis[x]) {
prime.emplace_back(x);
f[x] = 1 - x;
}
for (int p : prime) {
if (1LL * p * x > n) break;
vis[x * p] = 1;
f[x * p] = x % p ? (1 - p) * f[x] : f[x];
if (x % p == 0) break;
}
}
for (int x = 1; x <= n; ++x) {
f[x] = 1LL * x * f[x] % M + M;
f[x] = (f[x] + f[x - 1]) % M;
}
long long res = 0;
for (int l = 1, r; l <= n; l = r + 1) {
int nn = n / l, mm = m / l;
r = std::min(n / nn, m / mm);
int g_n = (1LL * nn * (nn + 1) / 2) % M;
int g_m = (1LL * mm * (mm + 1) / 2) % M;
res += 1LL * g_n * g_m % M * (f[r] - f[l - 1] + M) % M;
}
std::cout << (res % M) << '\n';
return 0;
}
The next example is special and requires transforming the divisor-counting function of a product.
LOJ 2185. [SDOI2015] Sum of Divisor Counts
test cases. For each case, compute:
Here denotes the number of divisors of .
Constraints: .
Solution
The difficulty is converting into an expression involving greatest common divisors. Since is multiplicative, first consider prime powers. For a prime and nonnegative exponents , let ; then
In general, write and , where are the powers in the prime factorizations of , respectively, corresponding to the prime . Then
Notice that, for each , enumerating its prime-power factors and their divisors is equivalent to enumerating 's divisors and then decomposing them into all prime-power factors ; the same holds for . By distributivity, this gives
conclusion:,if and only ifForeach , .
obtain , canApplications :
:function nonzerovalue, , satisfy When , satisfy .
, findsum :
Let ,
canbynumber theoryblock decompositionfind . need to sum prefix sum . time complexity ,where, , .
Referencescode
#include <algorithm>
#include <iostream>
using namespace std;
constexpr long long N = 5e4 + 5;
long long n, m, T, pr[N], mu[N], d[N], t[N],
cnt; // t denotes the number of times the smallest prime factor of i occurs.
bool bp[N];
void prime_work(long long k) {
bp[0] = bp[1] = true, mu[1] = 1, d[1] = 1;
for (long long i = 2; i <= k; i++) { // Linear sieve.
if (!bp[i]) pr[++cnt] = i, mu[i] = -1, d[i] = 2, t[i] = 1;
for (long long j = 1; j <= cnt && i * pr[j] <= k; j++) {
bp[i * pr[j]] = true;
if (i % pr[j] == 0) {
mu[i * pr[j]] = 0;
d[i * pr[j]] = d[i] / (t[i] + 1) * (t[i] + 2);
t[i * pr[j]] = t[i] + 1;
break;
} else {
mu[i * pr[j]] = -mu[i];
d[i * pr[j]] = d[i] << 1;
t[i * pr[j]] = 1;
}
}
}
for (long long i = 2; i <= k; i++)
mu[i] += mu[i - 1], d[i] += d[i - 1]; // Compute prefix sums.
}
long long solve() {
long long res = 0, mxi = min(n, m);
for (long long i = 1, j; i <= mxi; i = j + 1) { // Division into quotient blocks.
j = min(n / (n / i), m / (m / i));
res += d[n / i] * d[m / i] * (mu[j] - mu[i - 1]);
}
return res;
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
cin >> T;
prime_work(50000); // Precompute.
while (T--) {
cin >> n >> m;
cout << solve() << '\n';
}
return 0;
}
Example Applicationsmultiplication Möbius inversion.
Luogu P5221 Product
findvalue:
range:.
Note
process .Let
minimum multiple maximum :
Note, product independent ,canrespectivelycalculate.Let
:
calculateproblem. sum ,Howeverneed to corresponding multiplication . , :
where, Knuth . , , sum product ,obtain:
( Let ,), Applications function property, obtain:
with respect to product, ,Therefore When :
because , For need to findproduct .Let , :
Let
It is easy to with respect to product Möbius inversion. , canApplications Dirichlet difference method .When ,Because simple, candirectlyfind :
von Mangoldt function .obtain value ,directlyApplicationsproduct number theoryblock decomposition can find value, obtain value. time complexity .
value Note , product calculate ,oftenneed to ,Therefore the same.
Note
product productsum ,Therefore,For problem, can .For , Consider . , :
For maximum ,directlyApplications , obtain:
where, von Mangoldt function. , obtain .
Referencescode
#include <algorithm>
#include <iostream>
#include <vector>
int pow(int a, int b, int m) {
int res = 1;
for (int po = a; b; b >>= 1) {
if (b & 1) res = 1LL * res * po % m;
po = 1LL * po * po % m;
}
return res;
}
int main() {
constexpr int M = 104857601;
int n;
std::cin >> n;
// Get F(n), i.e., exp(Lambda(n)).
std::vector<int> vis(n + 1), prime, pf(n + 1), rem(n + 1);
prime.reserve(n);
for (int x = 2; x <= n; ++x) {
if (!vis[x]) {
prime.emplace_back(x);
pf[x] = x;
rem[x] = 1;
}
for (int p : prime) {
if (1LL * p * x > n) break;
vis[x * p] = 1;
pf[x * p] = p;
rem[x * p] = x % p ? x : rem[x];
if (x % p == 0) break;
}
}
pf[1] = 1;
for (int x = 2; x <= n; ++x) {
pf[x] = rem[x] == 1 ? pf[x] : 1;
}
// Prefix products and their inverses.
std::vector<int> pm(n + 1), ip(n + 1);
pm[0] = 1;
for (int x = 1; x <= n; ++x) {
pm[x] = 1LL * pm[x - 1] * pf[x] % M;
}
int inv = pow(pm[n], M - 2, M);
ip[0] = 1;
for (int x = n; x >= 1; --x) {
ip[x] = inv;
inv = 1LL * inv * pf[x] % M;
}
// Calculate g(n).
int res = 1;
for (int l = 1, r; l <= n; l = r + 1) {
r = n / (n / l);
int a = 1LL * pm[r] * ip[l - 1] % M;
int b = 1LL * (n / l) * (n / l) % (M - 1);
res = 1LL * res * pow(a, b, M) % M;
}
// Take square and then inverse.
res = pow(res, M - 3, M);
// Get factorials.
int fac = 1;
for (int x = 1; x <= n; ++x) {
fac = 1LL * fac * x % M;
}
// Final answer.
res = 1LL * res * pow(fac, 2 * n, M) % M;
std::cout << res << std::endl;
return 0;
}
Exercises
- Luogu P3312 [SDOI2014]
- Luogu P3700 [CQOI2017] Q
- Luogu P3704 [SDOI2017]
- Luogu P3768 simple
- Luogu P4464 [ ] JZPKIL
- Luogu P4619 [SDOI2018]
- Luogu P5518 [MtOI2019]
- Luogu P6222 simple
- Luogu P6825「EZEC-4」findsum
- Luogu P7486「Stoi2031」
- AtCoder Grand Contest 038 C - LCMs
- Codeforeces 1139 D. Steps to One