본문으로 건너뛰기
김신건의 로그

Mobius Function, Mobius Inversion

· 수정 · 📖 약 2분 · 842자/단어 #algorithm #math #mobius #number-theory #inversion
mobius-inversion, Mobius Function, Mobius Inversion, 뫼비우스 함수, 뫼비우스 역원, Dirichlet Convolution

정의

Mobius Function μ(n) 은 양의 정수에 대한 수론 함수:

μ(1) = 1
μ(n) = (-1)^k  if n = p_1 · p_2 · ... · p_k (서로 다른 소수의 곱)
μ(n) = 0       if n 이 어떤 소수의 제곱을 인수로 가짐

Mobius Inversion (뫼비우스 역원)합 / 컨볼루션 관계의 역변환. PS 에서는 GCD / 서로소 카운팅 의 표준 도구.

문제 상황과 동기

GCD / 서로소 카운팅 문제는 순진하게 O(N²) 또는 O(N² log N). 예를 들어 “1 ≤ i, j ≤ N, gcd(i, j) = 1 인 쌍의 수” 는 이중 루프로 O(N² log N) 이지만, Mobius 함수를 이용하면 Σ_d μ(d) · floor(N/d)² 로 정리되어 floor division blocking 기법으로 O(√N) 또는 O(N) 에 풀린다.

핵심 아이디어: [gcd(i, j) = 1] = Σ_{d | gcd(i, j)} μ(d) 라는 항등식. 합의 순서를 뒤집으면 Σ_d μ(d) · (N/d 의 배수 쌍 수) 꼴로 바뀌어 d 별로 O(1) 에 카운팅할 수 있다.

PS 에서는 GCD 조건을 뫼비우스 합으로 분해 → floor division blocking 으로 O(√N) 패턴이 정형. Dirichlet convolution 의 역원 성질을 이용해 약수 합 관계를 역변환 하는 것도 자주 등장.

문제 상황과 동기

Σ_{i=1..N} Σ_{j=1..N} [gcd(i,j) = 1] 같은 서로소 쌍 카운팅은 naive double loop 로 O(N² log N). N ≥ 10^6 이면 불가능.

Mobius function 과 floor(N/d) blocking 을 결합하면 이런 식을 O(√N) 로 줄일 수 있다. 핵심은 gcd 조건을 약수 합으로 바꾼 뒤 inversion 으로 역산하는 것. PS 에서 GCD 합 / 서로소 카운팅 / squarefree 집합 등이 이 트릭 없이는 풀 수 없다.

이 패턴은 Dirichlet ConvolutionEuler Phi 와도 밀접하다. 셋을 묶어서 “Mobius 계열 수론 트릭” 으로 부르기도 한다.

시각화

시각화

핵심 공식

Dirichlet Convolution

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

이 곱셈 환에서 μ 와 상수함수 1 은 서로 역원.

1 * μ = ε   (where ε(1) = 1, ε(n>1) = 0)

Mobius Inversion

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

또는 덮개 (cover) 버전:

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

핵심 응용

1. 서로소 카운팅

Σ_{i=1..N} Σ_{j=1..N} [gcd(i,j) = 1] = Σ_{d=1..N} μ(d) · floor(N/d)²

2. GCD 합 / LCM 합

Σ Σ gcd(i, j) = Σ_d φ(d) · floor(N/d)² 또는 mobius 로 직접.

Σ Σ lcm(i, j) = (i·j / gcd(i,j)) 의 합.

3. Coprime Integers 카운팅

Σ [gcd(a, b) = 1, 1 ≤ a ≤ A, 1 ≤ b ≤ B].

4. Square-free 카운팅

[n 이 squarefree] = |μ(n)|.

구현

선형 체로 μ 계산

// O(N) 선형 체. μ[1..N] 를 모두 계산.
#include <vector>
using namespace std;

vector<int> compute_mobius(int N) {
    vector<int> mu(N + 1, 1);
    vector<bool> is_prime(N + 1, true);
    vector<int> primes;

    for (int i = 2; i <= N; i++) {
        if (is_prime[i]) {
            primes.push_back(i);
            mu[i] = -1; // 한 개 소수
        }
        for (int p : primes) {
            if ((long long)i * p > N) break;
            is_prime[i * p] = false;
            if (i % p == 0) {
                mu[i * p] = 0; // p^2 인수 포함
                break;
            } else {
                mu[i * p] = -mu[i]; // 소수 한 개 추가
            }
        }
    }
    return mu;
}

서로소 쌍 카운팅 예시

// Σ_{1 ≤ i,j ≤ N} [gcd(i,j) = 1] 를 O(√N) 에 계산.
// blocking 으로 floor(N/d) 가 같은 구간 묶음.
#include <vector>
using namespace std;

long long coprime_count(int N) {
    auto mu = compute_mobius(N);
    long long ans = 0;
    
    // Σ_{d=1..N} μ(d) · ⌊N/d⌋²
    for (int d = 1; d <= N; ) {
        long long q = N / d;
        int next_d = N / q + 1;
        
        // d ~ (next_d-1) 구간에서 floor(N/d) = q 가 고정
        long long mu_sum = 0;
        for (int x = d; x < next_d && x <= N; x++) {
            mu_sum += mu[x];
        }
        ans += mu_sum * q * q;
        d = next_d;
    }
    return ans;
}

작은 입력 step trace

N = 4 일 때, Σ_{i,j=1..4} [gcd(i,j) = 1]

μ = [-, 1, -1, -1, 0]  (인덱스 0 무시)

Σ_{d=1..4} μ(d) · ⌊4/d⌋²
  = μ(1)·16 + μ(2)·4 + μ(3)·1 + μ(4)·1
  = 1·16 + (-1)·4 + (-1)·1 + 0·1
  = 16 - 4 - 1 = 11

실제로 (1,1), (1,2), (1,3), (1,4), (2,1), (2,3),
(3,1), (3,2), (3,4), (4,1), (4,3) = 11 쌍

응용 패턴

Σ_{i,j} f(gcd(i,j)) 같은 식을 풀 때:

Σ_{i,j} f(gcd(i,j))
  = Σ_d f(d) · # of (i,j) with gcd(i,j) = d
  = Σ_d f(d) · Σ_{k} μ(k) · floor(N/(d·k))²

이중 합을 blocking (floor(N/x) 가 같은 x 들을 묶음) 으로 O(N^0.6666666666666666) 또는 O(√N).

복잡도

작업비용
μ 선처리O(N)
단일 평가 (소인수분해)O(√n)
합 식 1회 (blocking)O(√N)

함정

1. μ(n) = 0 케이스

squarefree 가 아니면 0. 합에서 자연스럽게 무시되지만 항을 일일이 더하면 정확.

2. 합의 인덱스 범위

Σ_{d | n} vs Σ_{n | d}. 어느 쪽 합인지에 따라 inversion 공식이 다름.

3. 음수 mod

μ 는 -1 을 포함. mod p 에서 μ(n) ≡ p - 1 (if μ = -1) 로 처리.

4. φ (Euler totient) 와 혼동

φ 도 자주 같이 등장. Σ_{d|n} φ(d) = n, φ * 1 = id. 서로 다른 함수.

BOJ 연습 문제

번호제목링크
BOJ 16409Coprime Integerskokoa-lab
BOJ 14860GCD 곱kokoa-lab
BOJ 11691LCM(i, j)kokoa-lab
BOJ 14861LCM 더하기kokoa-lab

참고

이 글의 용어 (4개)
Euler Phi Function: φ(n)algorithm
정의 Euler Phi Function φ(n) 은 1 이상 n 이하 정수 중 n 과 서로소인 정수의 개수. 기존 Euler Phi 위키 참조. 이 페이지는 alias 확장용 축…
FWHT (Fast Walsh-Hadamard Transform)algorithm
정의 FWHT (Fast Walsh-Hadamard Transform) 은 비트 연산 (XOR, AND, OR) 에 대한 컨볼루션 을 O(N log N) 에 계산하는 변환. FF…
Generating Functionalgorithm
정의 Generating Function (생성 함수) 은 수열 를 형식 멱급수 (formal power series) 으로 인코딩한 것. 수열의 산수 를 다항식 / 멱급수의 대…
Stern-Brocot Treealgorithm
정의 Stern-Brocot Tree (SBT) 는 모든 양의 기약 분수 (positive coprime fraction) 를 정확히 한 번씩 노드로 가지는 무한 이진 트리. 1…

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기