Stern-Brocot Tree를 활용한 수론적 함수의 합 계산

개요

정수론에서 주로 다루는 중요한 수론적 함수로는 약수 함수 σk(n)\sigma_k (n), 오일러 피 함수 ϕ(n)\phi (n), 뫼비우스 함수 μ(n)\mu (n) 등이 있다. 이러한 함수의 학문적 중요도는 이루 말할 수 없으며, 컴퓨터과학와 PS 분야에도 종종 등장할 정도로 다양하게 활용된다.

본 글은 수론적 함수의 대표인 약수 함수 σ(n)\sigma (n)의 구간 합을 효율적으로 계산하는 알고리즘을 서술한다. 함수의 합을 기하적으로 해석한 후, 이를 Stern-Brocot Tree 자료구조로 계산한다. 이후, 이 알고리즘의 시간 복잡도가 O~(N1/3)\tilde{O} \left( N^{1/3} \right)로 아주 효율적임을 보인다.

문제 제기

약수 함수의 합 문제

양의 정수 nn에 대하여, nn의 모든 양의 약수의 kk제곱의 합을 생각하자. 이것이 약수 함수 σk(n)\sigma_k (n)의 정의이다.

σk(n):=∑d∣ndk\sigma_k (n) := \sum_{ d | n } d^k

이 글에서는 k=1k = 1인 시그마 함수 σ(n):=σ1(n)\sigma (n) := \sigma_1 (n)에 대하여 주로 다룬다. 이 값은 nn의 약수의 합을 나타낸다.

이제, 정수 NN이 주어졌을 때, 1부터 NN까지 시그마 함숫값의 합 ∑k=1Nσ(k)\displaystyle \sum_{k=1}^{N} \sigma(k)을 구하는 문제를 생각하자.

정수론적 접근

σ(1)+⋯+σ(N)\sigma(1) + \cdots + \sigma(N)의 값은 다음 조건을 만족하는 양의 정수 쌍 (n,d)(n, d)의 개수와 같다.

  1. dd는 nn의 약수
  2. 1≤d≤n≤N1 \le d \le n \le N

이는 시그마 함수의 정의를 생각할 때, σ(k)\sigma(k)의 값은 n=kn = k인 (n,d)(n, d)의 개수와 같으므로 자명하다.

이제, dd의 값을 고정한 후, 위의 조건을 만족하는 nn의 개수를 세자. nn은 NN 이하인 dd의 배수라야 하므로, 총 ⌊Nd⌋\displaystyle \left\lfloor \frac{ N }{ d } \right\rfloor개만큼 존재한다.

∑k=1Nσ(k)=∑d=1N⌊Nd⌋\sum _{k=1}^{N} \sigma(k) = \sum _{d=1}^{N} \left\lfloor \frac{ N }{ d } \right\rfloor

이는 다르게 해석하면, y=Nxy = \frac{N}{x} 그래프 아래에 있는 양의 정수 쌍 (x,y)(x, y)의 개수를 세는 것과 같다. 곡선 xy=Nxy = N은 직선 x=yx = y에 대하여 대칭이며, 이 둘의 교점은 (N,N)\left( \sqrt{N}, \sqrt{N} \right)이므로, 최종적으로 아래의 식을 얻을 수 있다.

∑d=1N⌊Nd⌋=2∑x=1⌊N⌋⌊Nx⌋−⌊N⌋2\sum _{d=1}^{N} \left\lfloor \frac{ N }{ d } \right\rfloor = 2 \sum _{x=1}^{ \left\lfloor \sqrt{N} \right\rfloor } \left\lfloor \frac{ N }{ x } \right\rfloor - { \left\lfloor \sqrt{N} \right\rfloor }^2

우리는 시그마 함수 σ(n)\sigma(n)의 값을 어떻게 계산하는지 알지 않아도, 시그마 함수의 합을 O(N)O \left( \sqrt{N} \right)만에 쉽게 계산할 수 있게 되었다.

그러나 NN이 101810^{18}-scale로 아주 큰 수라면, 우리는 이보다도 더욱 효율적인 방법을 찾아야 한다.

Stern-Brocot Tree

효율적인 알고리즘을 구상하기 전에, 페리 수열과 Stern-Brocot Tree 자료구조에 대하여 먼저 알아보자.

Farey Sequence

Stern-Brocot Tree에 대하여 논하기 전에, 먼저 페리 수열의 정의를 소개한다. nn번째 페리 수열 FnF_n는 다음을 만족하는 모든 기약분수 ab\displaystyle \frac{a}{b}를 오름차순으로 나열한 수열이다.

  1. 0≤b≤a≤n0 \le b \le a \le n
  2. gcd⁡(a,b)=1\gcd (a, b) = 1

예를 들어, 몇몇의 nn에 대하여 페리 수열 FnF_n을 나열하면 아래와 같다.

F1={01,11}F _1 = \left\{ \frac{0}{1}, \frac{1}{1} \right\} F2={01,12,11}F _2 = \left\{ \frac{0}{1}, \frac{1}{2}, \frac{1}{1} \right\} F5={01,15,14,13,25,12,35,23,34,45,11}F _5 = \left\{ \frac{0}{1}, \frac{1}{5}, \frac{1}{4}, \frac{1}{3}, \frac{2}{5}, \frac{1}{2}, \frac{3}{5}, \frac{2}{3}, \frac{3}{4}, \frac{4}{5}, \frac{1}{1} \right\}

여기서, 페리 수열 FnF_n에서 인접한 두 유리수를 "차수 nn에서 페리 이웃하다"라고 한다. 페리 이웃에 관한 중요한 정리를 하나 소개한다.

차수에 상관없이, 페리 이웃한 두 유리수 ab>cd\displaystyle \frac{a}{b} > \frac{c}{d}는 ad−bc=1ad - bc = 1을 만족한다.

이 정리는 아래에 서술할 Stern-Brocot Tree에 관한 정리의 기반이 된다.

Stern-Brocot Tree

페리 수열 FnF_n을 확장하여, 각 유리수의 역수까지 등장하는 수열을 생각하자. 편의상, 10=+∞\displaystyle \frac{1}{0} = + \infty로 생각하면, 이 수열은 01=0\displaystyle \frac{0}{1} = 0 이상 10=+∞\displaystyle \frac{1}{0} = + \infty 이하인 기약분수를 잘 나열할 것이다.

실제로, 00 이상의 모든 유리수는 충분히 큰 nn에 대하여 확장된 페리 수열 Fn′F' _n에 정확하게 한 번 등장함을 증명할 수 있다. 이제, 깊이 nn에 해당하는 층에 확장된 페리 수열 Fn′F' _n을 적어, 아래 그림과 같은 이진 트리를 생각하자.

그림 1: Stern–Brocot Tree

확장된 페리 수열 $F' _1$부터 $F' _4$까지 활용하여 깊이 4의 Stern-Brocot Tree를 만들 수 있다.

이 트리는 (1) 완전 이진 검색 트리이며, (2) 모든 양의 유리수가 정확하게 한 번씩 등장한다는 강력한 성질을 가진다. 또한, 트리 그 자체로 유리수와 자연수 간의 일대일 대응을 잘 보여준다.

이러한 완전 이진 검색 트리를 Stern-Brocot Tree라고 부른다.

유리수 이분탐색

알고리즘 분야에서 Stern-Brocot Tree는 유리수를 대상으로 이분탐색을 할 수 있게 되었다는 점에서 그 의미가 깊다.

두 유리수 ab<cd\displaystyle \frac{a}{b} < \frac{c}{d}에 대하여, ab\displaystyle \frac{a}{b} 초과 cd\displaystyle \frac{c}{d} 미만의 모든 유리수를 담고 있는 Stern-Brocot Subtree의 루트 정점은 a+cb+d\displaystyle \frac{a+c}{b+d}이다.

이를 그대로 활용하면, 다음과 같은 이분탐색 알고리즘을 생각할 수 있다.

  1. s:=ab=01\displaystyle s := \frac{a}{b} = \frac{0}{1}, e:=cd=10\displaystyle e := \frac{c}{d} = \frac{1}{0}으로 설정한다. 이제, 각 스텝마다 ss 초과 ee 미만인 유리수에 대하여 이분탐색을 수행한다.
  2. 중간값 m:=a+cb+d\displaystyle m := \frac{ a+c }{ b+d }을 잡자.
    1. 만약, mm이 찾고자 하는 유리수라면, 탐색을 멈춘다.
    2. 아니라면, 찾고자 하는 유리수와 mm에 대한 대소비교를 수행한다.
  3. (s,e)(s, e)를 (s,m)(s, m) 혹은 (m,e)(m, e)로 대입한 후, 위의 과정을 반복한다.

이러한 이분탐색 과정을 통하여 최종적으로 기약분수 xy\displaystyle \frac{x}{y}를 얻었다면, 탐색 횟수는 Stern-Brocot Tree에서 정점 xy\displaystyle \frac{x}{y}의 깊이와 같으므로 O(x+y)O(x+y)이다.

과정 2.는 Stern-Brocot Tree의 정점에서 한 쪽 방향으로 내려가는 것을 나타낸다. 여기서, 연속으로 몇 번까지 같은 방향으로 내려가는지를 알아낼 수 있다면 탐색 횟수를 줄일 수 있다. 예를 들어, 중간값 mm보다 작은 쪽으로 탐색을 이어나가야 한다면, ee 값을 ta+ctb+d\displaystyle \frac{ ta + c }{ tb + d } 꼴로 제한할 수 있다. 이것이 가능한 최대 정수 tt를 이분탐색으로 찾으면, 전체 탐색 횟수를 O(x+y)O(x+y)에서 O(x+lg⁡y)O \left( x + \lg y \right)로 크게 개선할 수 있다.

기하적 접근

다시 원래의 문제로 돌아오자. 우리는 아래의 그림과 같이 y=Nx\displaystyle y = \frac{N}{x} 곡선 아래의 회색 영역에 존재하는 양의 정수 쌍 (x,y)(x, y)의 수를 세어야 한다.

그림 2: $xy = 20$ 그래프와 회색 영역

$N = 20$이라면 위 회색 영역 내부의 정수 점의 개수를 세어야 한다.

이 그래프에서 기울기가 −1-1인 접선을 긋자. 아래의 그림에 접점 GG, xx 축과 yy 축과의 교점 PxP _x, PyP _y을 나타내었다.

그림 3: $xy = 20$ 그래프와 기울기 $-1$의 접선

접점 $G$와 중요한 교점 두 개 $P _x$, $P _y$를 나타내었다. 접선 아래 영역의 정수 점의 개수는 쉽게 셀 수 있다.

여기서 아이디어는 이러하다. 곡선 아래의 정수 점의 개수를 세는 것은 어렵지만, 직선 아래의 정수 점의 수는 사칙연산을 이용하여 아주 쉽게 셀 수 있다.

우리는 남은 영역에 대하여 적당한 기울기의 접선을 그어 점의 개수를 세는 작업을 재귀적으로 반복하고자 한다. 정수 점의 개수는 유한하므로, 접선의 기울기를 잘 설정하였다면, 이러한 작업은 유한 시간 안에 종료할 것이다.

편의를 위하여, 그림 4와 같은 영역 내부의 정수 점의 개수를 f(x0,y0,ab,cd)\displaystyle f \left( x _0, y _0, \frac{a}{b}, \frac{c}{d} \right)로 나타내자. 이에 대한 엄밀한 정의는 다음과 같다.

음이 아닌 정수 x0x _0, y0y _0과 페리 이웃한 두 기약분수 ab\displaystyle \frac{a}{b}, cd\displaystyle \frac{c}{d}에 대하여,

  1. 점 P(x0,y0)P \left( x _0, y _0 \right)을 잡고
  2. 점 PP로부터 각각 기울기 −ab\displaystyle - \frac{a}{b}, −cd\displaystyle - \frac{c}{d}의 접선을 그어 교점 QQ, RR를 잡았을 때
  3. 직선과 곡선으로 닫힌 삼각 영역 PQRPQR 내부의 정수 점의 개수를 f(x0,y0,ab,cd)\displaystyle f \left( x _0, y _0, \frac{a}{b}, \frac{c}{d} \right)로 정의한다.
  4. 인자가 상기한 조건을 만족하지 않으면, 편의상 f(x0,y0,ab,cd)=0\displaystyle f \left( x _0, y _0, \frac{a}{b}, \frac{c}{d} \right) = 0으로 정의한다.

그림 4: 점 $P$, $Q$, $R$과 회색 삼각 영역

$\displaystyle f \left( x _0, y _0, \frac{a}{b}, \frac{c}{d} \right)$의 정의에서 사용되는 세 점을 나타내었다.

우리는 결국 f(x0,y0,ab,cd)\displaystyle f \left( x _0, y _0, \frac{a}{b}, \frac{c}{d} \right)가 0이 될 때까지 재귀적으로 탐색을 이어나가야 한다. 따라서, 이 함숫값을 계산할 수 있어야 한다. 이를 어떻게 계산할 수 있을까?

그림 4의 두 접선을 각각 새로운 축으로 잡고, 점 PP를 원점으로 생각한 새로운 좌표계 u−vu-v를 생각하자. uu 축이 직선 PRPR, vv 축이 직선 PQPQ이다. 이 경우 회색 영역은 다음과 같이 변환된다.

그림 5: 변환된 새로운 영역

드디어 우리는 재귀적으로 정수 점의 개수를 셀 수 있게 되었다!

시간 복잡도

재귀적으로 변하는 접선의 기울기는 Stern-Brocot Tree에서 경로를 따라 아래로 내려가는 것과 같으므로, 시간 복잡도를 아래와 같이 쓸 수 있다.

O(∑ad−bc=1I[Nc/d−Na/b≥b+d])O \left( \sum _{ ad - bc = 1 } I \left[ \sqrt{ \frac{N}{ c/d } } - \sqrt{ \frac{N}{ a/b } } \ge b + d \right] \right) =O(∑ad−bc=1I[bc+1−bcac≥b+dN])= O \left( \sum _{ ad - bc = 1 } I \left[ \frac{ \sqrt{bc + 1} - \sqrt{bc} }{ \sqrt{ac} } \ge \frac{ b + d }{ \sqrt{N} } \right] \right) =O(∑ad−bc=1I[1abc≥b+dN])=O(∑ad−bc=1I[abc2(b+d)2≥N])= O \left( \sum _{ ad - bc = 1} I \left[ \frac{1}{ \sqrt{ab} c } \ge \frac{b+d}{\sqrt{N}} \right] \right) = O \left( \sum _{ad - bc = 1} I \left[ ab c^2 \left( b + d \right)^2 \ge N \right] \right)

마지막 줄에서는 x+1−x=O(1x)\displaystyle \sqrt{x+1} - \sqrt{x} = O \left( \frac{1}{ \sqrt{x} } \right)가 사용되었다.

이제, t=bct = bc 치환을 적용하면,

O(∑t∑b∣t∑a∣(t+1)I[t4ab+t3+abt2≥N])O \left( \sum _{t} \sum _{ b | t} \sum _{ a | (t+1) } I \left[ \frac{t^4}{ab} + t^3 + ab t^2 \ge N \right] \right) =O(∑t=1N1/3σ(t)σ(t+1))=O(∑t=1N1/3σ2(t))= O \left( \sum _{t = 1}^{N^{1/3}} \sigma(t) \sigma(t+1) \right) = O \left( \sum _{t=1}^{N^{1/3}} \sigma^2 (t) \right)

엄밀한 증명이나 식 전개는 생략하였다.

이제, 다음의 잘 알려진 정리를 적용하자.

∑k=1Nσ2(k)=Θ(Nlg⁡3N)\sum _{k=1}^{N} \sigma^2 (k) = \Theta \left( N \lg^3 N \right)

즉, 서술한 알고리즘의 시간 복잡도는 O(N13lg⁡3N)=O~(N13)\displaystyle O \left( N^{ \frac{1}{3} } \lg^3 N \right) = \tilde{O}\left( N^{ \frac{1}{3} } \right) 임을 알 수 있다.

결론

수론적 함수는 정수론 뿐만 아니라 컴퓨터과학, 알고리즘, PS 분야에도 사용될 정도로 중요하며 그 폭이 아주 넓다.

우리는 대표적인 수론적 함수 σ(n)\sigma (n)의 구간 합 ∑k=1Nσ(k)\displaystyle \sum _{k=1}^{N} \sigma(k)을 효율적으로 계산하는 알고리즘에 대하여 알아보았다.

일반적인 식 전개로는 O(N)\displaystyle O \left( \sqrt{N} \right)까지 시간 복잡도를 줄일 수 있었다. 그러나, NN이 아주 큰 수라면 이 방법도 아직은 느리다.

우리는 y=Nx\displaystyle y = \frac{N}{x} 그래프와 구하고자 하는 값과의 관계를 알아내고, 그래프의 볼록성이라는 기하적 특성과 Stern-Brocot Tree 자료구조를 활용하여, 재귀적으로 값을 계산하는 새로운 알고리즘을 조사하였다.

또한, 이 알고리즘의 시간 복잡도가 O~(N1/3)\displaystyle \tilde{O} \left( N^{1/3} \right)로 아주 효율적임을 밝혔다.

이러한 알고리즘의 아이디어는 다양한 볼록 함수에 대하여 접목시킬 수 있으며, 그 응용성이 높다. 다음 글에는 σ(n)\sigma (n) 외에 다른 수론적 함수의 구간 합을 효율적으로 계산하는 방법에 대하여 알아본다.