Multidimensional Sieve
The Mobius function mu(n) and Mobius inversion extend to multiple dimensions. Given an arithmetic function f(n_1,..., n_k), compute its Mobius inversion efficiently.
Problem Statement
This archive keeps the full statement, math, and original media on the page.
Two players play a game with a number of piles of stones, alternating turns. Each turn a player can choose to remove 1, 2, 4, or 9 stones from a single pile; or alternatively they can choose to split a pile containing two or more stones into two non-empty piles. The winner is the player who removes the last stone.
A collection of piles is called a losing position if the player to move cannot force a win with optimal play. Define \(S(N, m)\) to be the number of distinct losing positions arising from \(m\) piles of stones where each pile contains from \(1\) to \(N\) stones. Two positions are considered equivalent if they consist of the same pile sizes. That is, the order of the piles does not matter.
You are given \(S(12,4)=204\) and \(S(124,9)=2259208528408\).
Find \(S(12491249,1249)\). Give your answer modulo \(912491249\).
Problem 888: Multidimensional Sieve
Mathematical Analysis
Theorem 1 (Mobius Inversion, 1D)
If , then .
Proof.
using .
Theorem 2 (Multidimensional Inversion)
If , then:
Theorem 3 (Inclusion-Exclusion Connection)
For squarefree arguments, Mobius inversion reduces to inclusion-exclusion:
where is the set of prime factors of .
Theorem 4 (Sieve of Coprime Tuples)
The number of -tuples with and :
Proof. By Mobius inversion on :
Concrete Numerical Examples
Mobius Function Values
| Reason | ||
|---|---|---|
| 1 | 1 | Empty product |
| 2 | One prime factor | |
| 3 | One prime factor | |
| 4 | 0 | , not squarefree |
| 5 | Prime | |
| 6 | 1 | , two factors |
| 12 | 0 | |
| 30 | , three factors |
Coprime Pairs
| Direct count | ||
|---|---|---|
| 1 | 1 | 1 |
| 2 | 3 | 3 |
| 3 | 7 | 7 |
| 5 | 19 | 19 |
| 10 | 63 | 63 |
Euler Totient via Mobius
| 6 | 2 | |
| 12 | 4 | |
| 30 | 8 |
Dirichlet Convolution
The Mobius function is the Dirichlet inverse of the constant function . For arithmetic functions :
Key identities:
- (identity for Dirichlet convolution)
- (Euler’s totient)
- (divisor power sum)
Mertens Function
. The Mertens conjecture was disproven by Odlyzko and te Riele (1985), but is equivalent to the Riemann Hypothesis.
Complexity Analysis
| Operation | Time |
|---|---|
| Sieve up to | |
| via Mobius sieve | |
| Multidimensional Mobius transform | |
| Dirichlet convolution | or |
Answer
Code
Each problem page includes the exact C++ and Python source files from the local archive.
/*
* Problem 888: Multidimensional Sieve
* Mobius function sieve and coprime tuple counting.
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<int> mobius_sieve(int N) {
vector<int> mu(N + 1, 0), primes;
vector<bool> is_prime(N + 1, true);
mu[1] = 1;
for (int i = 2; i <= N; i++) {
if (is_prime[i]) { primes.push_back(i); mu[i] = -1; }
for (int p : primes) {
if ((ll)i * p > N) break;
is_prime[i * p] = false;
if (i % p == 0) { mu[i * p] = 0; break; }
else mu[i * p] = -mu[i];
}
}
return mu;
}
ll coprime_pairs(int N, const vector<int>& mu) {
ll total = 0;
for (int d = 1; d <= N; d++)
total += (ll)mu[d] * (N / d) * (N / d);
return total;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int N = 1000;
auto mu = mobius_sieve(N);
cout << "=== Mobius Function ===" << endl;
for (int n = 1; n <= 30; n++)
cout << "mu(" << n << ") = " << mu[n] << endl;
cout << "\n=== Coprime Pairs ===" << endl;
for (int n : {10, 50, 100, 500, 1000})
cout << "C_2(" << n << ") = " << coprime_pairs(n, mu) << endl;
cout << "\nAnswer: C_2(1000) = " << coprime_pairs(1000, mu) << endl;
return 0;
}
"""
Problem 888: Multidimensional Sieve
Mobius inversion and inclusion-exclusion over prime factors.
"""
from math import gcd, isqrt
def mobius_sieve(N):
"""Compute mu(n) for n = 0..N."""
mu = [0] * (N + 1)
mu[1] = 1
is_prime = [True] * (N + 1)
primes = []
for i in range(2, N + 1):
if is_prime[i]:
primes.append(i)
mu[i] = -1
for p in primes:
if i * p > N:
break
is_prime[i * p] = False
if i % p == 0:
mu[i * p] = 0
break
else:
mu[i * p] = -mu[i]
return mu
def coprime_pairs(N, mu):
"""Count pairs (a,b) in [1,N]^2 with gcd(a,b) = 1."""
total = 0
for d in range(1, N + 1):
total += mu[d] * (N // d) ** 2
return total
def coprime_pairs_brute(N):
"""Brute force count."""
count = 0
for a in range(1, N + 1):
for b in range(1, N + 1):
if gcd(a, b) == 1:
count += 1
return count
def euler_totient_via_mobius(n, mu):
"""phi(n) = sum_{d|n} mu(d) * (n/d)."""
total = 0
for d in range(1, n + 1):
if n % d == 0:
total += mu[d] * (n // d)
return total
# --- Verification ---
N = 100
mu = mobius_sieve(N)
print("=== Mobius Function ===")
for n in range(1, 31):
print(f" mu({n:>2}) = {mu[n]:>2}")
print("\n=== Coprime Pairs ===")
for N_test in [1, 2, 3, 5, 10, 20]:
fast = coprime_pairs(N_test, mu)
brute = coprime_pairs_brute(N_test)
print(f" C_2({N_test:>2}) = {fast:>5} (fast), {brute:>5} (brute), "
f"{'OK' if fast == brute else 'FAIL'}")
assert fast == brute
print("\n=== Euler Totient via Mobius ===")
for n in [1, 2, 3, 4, 6, 10, 12, 20, 30]:
phi = euler_totient_via_mobius(n, mu)
print(f" phi({n:>2}) = {phi}")
print("\n=== Verification: sum mu(d) for d|n ===")
for n in [1, 2, 6, 12, 30]:
s = sum(mu[d] for d in range(1, n + 1) if n % d == 0)
print(f" sum mu(d) for d|{n} = {s} (should be {'1' if n == 1 else '0'})")
assert s == (1 if n == 1 else 0)
answer = coprime_pairs(100, mu)
print(f"\nAnswer: C_2(100) = {answer}")
# --- 4-Panel Visualization ---