Open In App

Introduction to Möbius inversion

Last Updated : 24 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

The Mobius inversion formula is a technique used in number theory to find the inverse of an arithmetic function. It is based on the Mobius function, which is a function that assigns a value of -1, 0, or 1 to each positive integer based on its prime factorization. 

mobius inversion function

The basic idea behind Mobius Inversion is to express a given function f(n) as a linear combination of the Mobius function μ(n), which is defined as follows:

μ(n) = 1 if n is a square-free positive integer with an even number of prime factors
= -1 if n is a square-free positive integer with an odd number of prime factors
= 0 if n is not square-free

Formula Derivation:

The Möbius inversion formula states that for any arithmetic functions f(n) and g(n) such that

g(n) = Σ_{d|n} f(d)

where the sum is taken over all positive divisors d of n, the function f(n) can be recovered from g(n) via the following formula:

f(n) = Σ_{d|n} μ(d)g(n/d)

where μ(n) is the Möbius function, which is defined as:

μ(n) = 1 if n is a square-free number with an even number of prime factors -1 if n is a square-free number with an odd number of prime factors 0 if n is not square-free

To derive this formula, we start by multiplying both sides of the original equation by μ(n), and then summing over all positive integers n:

Σ_{n=1} μ(n) g(n) = Σ_{n=1} μ(n) Σ_{d | n} f(d)

  • Interchanging the order of summation and using the properties of the Möbius function, we get:
    • Σ_{n=1} μ(n) g(n) = Σ_{d=1} f(d) Σ_{n=1} μ(n) [d | n]
  • Now, we note that the inner sum is non-zero only when d divides n, and in that case, it is equal to μ(n/d). So we can write:
    • Σ_{n=1} μ(n) g(n) = Σ_{d=1}f(d) Σ_{n=1} μ(n/d) [d | n]
  • Finally, changing the index of the summation, we get:
    • Σ_{n=1} μ(n) g(n) = Σ_{d=1} f(d) Σ_{k=1} μ(k) [d | k]
  • Now, we can see that the inner sum is equal to 1 if d divides k and 0 otherwise, so we get:
    • Σ_{n=1} μ(n) g(n) = Σ_{d=1} f(d)

Since both sides are equal, we can say:

Σ_{n=1} μ(n) g(n) = Σ_{d=1} f(d)
or
g(n) = Σ_{d|n} f(d)
f(n) = Σ_{d|n} μ(d)g(n/d)

which is the Möbius inversion formula.

Example:

Let’s take an example to understand this better:

Example: Let’s say we have a function f(n) = n. We want to find the inverse function h(n) of this function.

Step 1: We define g(n) = ∑f(d)μ(n/d) = ∑d*μ(n/d)
Step 2: We define h(n) = ∑g(d)μ(n/d) = ∑(∑d*μ(n/d))μ(n/d) = ∑dμ(d)

We can see that h(n) = 1 if n = 1, and h(n) = 0 for all other positive integers.

In programming, the most common way to implement Mobius Inversion is by precomputing the values of the Mobius function for all integers up to a certain limit and then using these precomputed values to quickly compute the inverse function of a given function.

Here is a step-by-step algorithm for Mobius Inversion in C++:

  • Precompute the Mobius function for all integers up to a certain limit (N in this case). This can be done using a function that loops through all integers from 1 to N and uses the definition of the Mobius function to determine the value of the function for each integer.
  • Define the function to be inverted, f(n), as an array of integers.
  • Define the function g(n) = ∑f(d)μ(n/d) for all positive divisors d of n. This can be done by looping through all divisors of n, and using the precomputed values of the Mobius function to calculate the value of g(n) for each divisor.
  • Define the inverse function h(n) = ∑g(d)μ(n/d) for all positive divisors d of n. This can be done by looping through all divisors of n, and using the precomputed values of the Mobius function and the previously calculated value of g(n) to calculate the value of h(n) for each divisor.
  • Return the value of h(n) as the result of the inverse function for the input value n.
  • It’s important to note that for a given function f(n), the inverse function h(n) is only guaranteed to be correct if the input function satisfies the condition that the sum of the function over all positive integers is equal to zero.
  • The function can be tested with different input values of n and check the output.
  • The algorithm can be optimized by using techniques such as memoization and sieving to improve its performance.
  • Additional error handling and validation checks can be added to ensure that the input values are within the expected range and that the input function satisfies the condition mentioned in step 6.
  • The algorithm can also be modified to handle more complex functions and larger input values by increasing the limit of precomputing the Mobius function and updating the function to calculate the inverse function.

It’s important to note that this is a basic example and the algorithm can be adjusted and optimized as needed depending on the specific problem you are trying to solve.

Here is an example of how to implement Mobius Inversion in C++

C++




// C++ code to implement the Mobius inversion
  
#include <bits/stdc++.h>
using namespace std;
  
// Set the limit for precomputing the Mobius function
const int N = 20;
int mobius[N + 1];
  
// Function to precompute the Mobius function
void precompute_mobius()
{
    for (int i = 1; i <= N; i++) {
        mobius[i] = 1;
    }
    for (int i = 2; i <= N; i++) {
        if (mobius[i] == 1) {
            for (int j = i; j <= N; j += i) {
                if (j % (i * i) == 0) {
                    mobius[j] = 0;
                }
                else {
                    mobius[j] *= -1;
                }
            }
        }
    }
}
  
// Function to compute the inverse
// of a given function using Mobius Inversion
int inverse_function(int n, int f[])
{
    int result = 0;
    for (int d = 1; d <= n; d++) {
        int g = 0;
        for (int i = 1; i <= n / d; i++) {
            g += f[i] * mobius[i];
        }
        result += g * mobius[n / d];
    }
    return result;
}
  
// Driver Code
int main()
{
  
    // Precompute the Mobius function
    precompute_mobius();
  
    // Example function
    int f[N + 1] = {
        0, 1, 3, 0, 2, 10, 7, 0, 5, 0,
        0, 4, 0, 0, 0, 0, 8, 0, 0, 6
    };
  
    // Example value to compute inverse function
    int n = 10;
    int h = inverse_function(n, f);
    cout << "The inverse of f(n) for n = " << n
         << " is: " << h << endl;
    return 0;
}


Python3




# Python code to implement the Mobius inversion
  
N = 20
mobius = [1] * (N + 1)
  
# Function to precompute the Mobius function
def precompute_mobius():
    for i in range(2, N + 1):
        if mobius[i] == 1:
            for j in range(i, N + 1, i):
                if j % (i * i) == 0:
                    mobius[j] = 0
                else:
                    mobius[j] *= -1
  
# Function to compute the inverse
# of a given function using Mobius Inversion
def inverse_function(n, f):
    result = 0
    for d in range(1, n + 1):
        g = 0
        for i in range(1, n // d + 1):
            g += f[i] * mobius[i]
        result += g * mobius[n // d]
    return result
  
# Precompute the Mobius function
if __name__ == '__main__':
    
    precompute_mobius()
      
    # Example function
    f = [0, 1, 3, 0, 2, 10, 7, 0, 5, 0, 0, 4, 0, 0, 0, 0, 8, 0, 0, 6]
      
    # Example value to compute inverse function\
    n = 10
    h = inverse_function(n, f)
    print("The inverse of f(n) for n = ", n, " is: ", h)


Java




import java.util.*;
  
public class MobiusInversion {
    // Set the limit for precomputing the Mobius function
    static final int N = 20;
    static int[] mobius = new int[N + 1];
  
    // Function to precompute the Mobius function
    public static void precomputeMobius()
    {
        Arrays.fill(mobius, 1);
        for (int i = 2; i <= N; i++) {
            if (mobius[i] == 1) {
                for (int j = i; j <= N; j += i) {
                    if (j % (i * i) == 0) {
                        mobius[j] = 0;
                    }
                    else {
                        mobius[j] *= -1;
                    }
                }
            }
        }
    }
  
    // Function to compute the inverse
    // of a given function using Mobius Inversion
    public static int inverseFunction(int n, int[] f)
    {
        int result = 0;
        for (int d = 1; d <= n; d++) {
            int g = 0;
            for (int i = 1; i <= n / d; i++) {
                g += f[i] * mobius[i];
            }
            result += g * mobius[n / d];
        }
        return result;
    }
  
    // Driver Code
    public static void main(String[] args)
    {
        // Precompute the Mobius function
        precomputeMobius();
  
        // Example function
        int[] f = {
            0, 1, 3, 0, 2, 10, 7, 0, 5, 0,
            0, 4, 0, 0, 0, 0, 8, 0, 0, 6
        };
  
        // Example value to compute inverse function
        int n = 10;
        int h = inverseFunction(n, f);
        System.out.println("The inverse of f(n) for n = " + n + " is: " + h);
    }
}


C#




using System;
  
public class MobiusInversion {
    // Set the limit for precomputing the Mobius function
    static int N = 20;
    static int[] mobius = new int[N + 1];
  
    // Function to precompute the Mobius function
    public static void precomputeMobius()
    {
        Array.Fill(mobius, 1);
        for (int i = 2; i <= N; i++) {
            if (mobius[i] == 1) {
                for (int j = i; j <= N; j += i) {
                    if (j % (i * i) == 0) {
                        mobius[j] = 0;
                    }
                    else {
                        mobius[j] *= -1;
                    }
                }
            }
        }
    }
  
    // Function to compute the inverse
    // of a given function using Mobius Inversion
    public static int inverseFunction(int n, int[] f)
    {
        int result = 0;
        for (int d = 1; d <= n; d++) {
            int g = 0;
            for (int i = 1; i <= n / d; i++) {
                g += f[i] * mobius[i];
            }
            result += g * mobius[n / d];
        }
        return result;
    }
  
    // Driver Code
    public static void Main(string[] args)
    {
        // Precompute the Mobius function
        precomputeMobius();
  
        // Example function
        int[] f = { 0, 1, 3, 0, 2, 10, 7, 0, 5, 0,
                    0, 4, 0, 0, 0, 0, 8, 0, 0, 6 };
  
        // Example value to compute inverse function
        int n = 10;
        int h = inverseFunction(n, f);
        Console.WriteLine("The inverse of f(n) for n = " + n
                          + " is: " + h);
    }
}


Javascript




// JavaScript code to implement the Mobius inversion
// Set the limit for precomputing the Mobius function
const N = 20;
const mobius = new Array(N + 1).fill(1);
  
// Function to precompute the Mobius function
function precomputeMobius() {
  for (let i = 2; i <= N; i++) {
    if (mobius[i] == 1) {
      for (let j = i; j <= N; j += i) {
        if (j % (i * i) == 0) {
          mobius[j] = 0;
        } else {
          mobius[j] *= -1;
        }
      }
    }
  }
}
  
// Function to compute the inverse
// of a given function using Mobius Inversion
function inverseFunction(n, f) {
  let result = 0;
  for (let d = 1; d <= n; d++) {
    let g = 0;
    let x = Math.floor(n/d);
    for (let i = 1; i <= x; i++) {
      g += f[i] * mobius[i];
    }
    result += g * mobius[x];
  }
  return result;
}
  
// Precompute the Mobius function
precomputeMobius();
  
// Example function
const f = [
  0, 1, 3, 0, 2, 10, 7, 0, 5, 0,
  0, 4, 0, 0, 0, 0, 8, 0, 0, 6
];
  
// Example value to compute inverse function
const n = 10;
const h = inverseFunction(n, f);
console.log(`The inverse of f(n) for n = ${n} is: ${h}`);


Output

The inverse of f(n) for n = 10 is: 42

Code Breakdown:

In this example,  

  • We first define a constant N that represents the limit for precomputing the Mobius function. 
  • We then create an array mobius[N + 1] to store the precomputed values of the Mobius function. 
  • The function precompute_mobius() is used to precompute the values of the Mobius function for all integers up to the limit N.
  • We then define a function inverse_function() that takes as input an integer n and an array f[] representing

The output of the Mobius Inversion implementation in C++ will depend on the specific function that is provided as input. Without a specific definition for the function f(n) and an input value for n, it is impossible to determine the exact output of the function.

It’s important to note that the output value of the inverse function is only guaranteed to be correct if the input function satisfies the condition that the sum of the function over all positive integers is equal to zero.

Complexity analysis:

The time and space complexity of the Mobius Inversion algorithm in C++ will depend on the specific implementation and the size of the input values.

In the example,   

  • Time Complexity:
    • The time complexity of precomputing the Mobius function is O(N * log(log N)) where N is the limit for precomputing the Mobius function. This is because we are iterating through all integers up to N and for each number, we are iterating through all of its divisors. 
    • The time complexity of the inverse_function() is O(n*log n) where n is the input value; because we are iterating through all divisors of n and for each divisor, we are iterating through all integers up to n/d.
  • Space Complexity:
    • The space complexity is O(N) because we are storing the precomputed values of the Mobius function in an array of size N+1.
    • The space complexity of the inverse_function(int n, int f[]) is O(1) because we are not using any additional data structures to store the intermediate results.


Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads