A Introduction to FFT (Fast Fourier Transform) Algorithm with its application in competitive programming. This talk was given in the 2012 SNUPS (Seoul National University Problem Solving Group) Algorithm seminar.
평범한 방법 O(n2) C(z) = A(z)B(z) = c0 + c1z + · · · + c2n−2x2n−2, where ci = a0bi + a1bi−1 + · · · + aib0 좀 더 빠르게 하고 싶습니다. FFT! (Fast Fourier Transform) Jongwook Choi Fast Fourier Transform
신묘한 방법 Idea. m − 1차 다항식은 m개의 점에서의 함수값이 결정되면 유일하게 결정된다 (Lagrange’s Interpolation). C(z) 의 degree 는 (at most) 2n − 2 이므로, 서로 다른 2n − 1 개의 점에 대해 C 의 함수값만 알면 되겠다. Jongwook Choi Fast Fourier Transform
신묘한 방법 Idea. m − 1차 다항식은 m개의 점에서의 함수값이 결정되면 유일하게 결정된다 (Lagrange’s Interpolation). C(z) 의 degree 는 (at most) 2n − 2 이므로, 서로 다른 2n − 1 개의 점에 대해 C 의 함수값만 알면 되겠다. 서로 다른 2n − 1 개의 점 z0, z1, · · · , z2n−2 에 대해, A(z0), A(z1), · · · , A(z2n−2) 와 B(z0), B(z1), · · · , B(z2n−2) 를 안다면, C(z0), C(z1), · · · , C(z2n−2) 를 빠르게 계산할 수 있지 않을까? Jongwook Choi Fast Fourier Transform
Multiplication by FFT 서로 다른 2n − 1 개의 점 z0, z1, · · · , z2n−2 에 대해, A(z0), A(z1), · · · , A(z2n−2) 와 B(z0), B(z1), · · · , B(z2n−2) 를 안다면, C(z0), C(z1), · · · , C(z2n−2) 를 빠르게 계산할 수 있지 않을까? Jongwook Choi Fast Fourier Transform
Multiplication by FFT 서로 다른 2n − 1 개의 점 z0, z1, · · · , z2n−2 에 대해, A(z0), A(z1), · · · , A(z2n−2) 와 B(z0), B(z1), · · · , B(z2n−2) 를 안다면, C(z0), C(z1), · · · , C(z2n−2) 를 빠르게 계산할 수 있지 않을까? C(zk) = A(zk) · B(zk) k = 0, 1, · · · , 2n − 2 Jongwook Choi Fast Fourier Transform
Discrete Fourier Transform 다항식 A(x) = a0 + a1x + · · · + an−1xn−1 을 생각하자. ω ∈ C 을 primitive root of unity (ωn = 1 라는 말) 라고 할 때, n개의 점 ω0, ω1, ω2, · · · , ωn−1 에서의 함수값 A(ωi) = n−1 j=0 aj(ωi)j 들을 모으면 n 개의 수가 얻어진다. Jongwook Choi Fast Fourier Transform
Discrete Fourier Transform 다항식 A(x) = a0 + a1x + · · · + an−1xn−1 을 생각하자. ω ∈ C 을 primitive root of unity (ωn = 1 라는 말) 라고 할 때, n개의 점 ω0, ω1, ω2, · · · , ωn−1 에서의 함수값 A(ωi) = n−1 j=0 aj(ωi)j 들을 모으면 n 개의 수가 얻어진다. 이 때 transform Cn → Cn (a0, a1, · · · , an−1) → (A(a0), A(a1), · · · , A(an−1)) 를 DFT (이산 푸리에 변환) 이라고 한다. Jongwook Choi Fast Fourier Transform
그래서 우리의 관심은 DFT 구하는 것, 즉 ω0, · · · , ωn−1 에서의 함수값 A(ω0), · · · , A(ωn−1) 을 모두 알아낼 수 있으면 OK. 얼마나 빨리? O(n log n) naive 하게 계산하면 O(n2) 인데 그러면 하나마나. Jongwook Choi Fast Fourier Transform
역변환 거꾸로, DFT의 결과를 알고 있을 때 원래 다항식을 구하는 방법은? 즉, 최대 2n차 다항식 C에 대해 C(ω0), C(ω1), · · · , C(ω2n−1) 를 알고 있을 때 (ω2n = 1) C의 계수 c0, c1, · · · , c2n−1 를 구하려면 어떻게 하는가? Jongwook Choi Fast Fourier Transform
DFT 역변환 n − 1차 다항식 A(x) 에 대해 wn = 1이고, yk = A(wk) 를 모두 알고 있다고 하자. (k = 0, 1, 2, · · · , n − 1) yk = A(wk) = n−1 j=0 aj(wk)j Jongwook Choi Fast Fourier Transform
DFT 역변환 즉, (y0, y1, · · · , yn−1) 를 DFT 하는데 ω를 ω−1 로 replace 하고 최종 결과를 n 으로 나누면 (a0, a1, a2, · · · , an−1) 이 얻어진다. 즉 FFT 함수가 있으면 역변환 하는것도 바로 된다. O(n log n) Jongwook Choi Fast Fourier Transform
Remark DFT 를 구할 때, FFT 계산 시 n을 2의 power라고 가정하고 있음. 실수 연산을 해야하기 때문에 실수 오차가 발생할 수 있다. (input 다항식의 계수가 정수라고 가정하면) 최종적으로 얻어진 cj 계수들이 정수가 아닐 수도 있는데, 가장 가까운 integer로 반올림하면 된다. (오차 0.5 미만이면 OK) 실수 연산 없이, finite field Zp (n | p − 1) 에서 ω의 역할을 하는 primitive root of unity 를 쓰면 정수 연산만으로도 되는데 (Number Theoretic Transform), 뭔가 엄청 복잡하고 실제로도 나눗셈 연산때문에 더 느림. (CRLS Problem 30-6 참고) FFT는 팀노트에 넣어가면 좋다. Jongwook Choi Fast Fourier Transform
예제 문제. 두 n-length array A = (a0, · · · , an−1), B = (b0, · · · , bn−1) 가 있다. 이 때 A와 B의 convolution C = A ∗ B = (c0, · · · , cn−1) cj = j k=0 akbj−k 를 구하시오. 단, n은 무지무지 큼. Jongwook Choi Fast Fourier Transform
예제 문제. 두 n-length array A = (a0, · · · , an−1), B = (b0, · · · , bn−1) 가 있다. 이 때 A와 B의 convolution C = A ∗ B = (c0, · · · , cn−1) cj = j k=0 akbj−k 를 구하시오. 단, n은 무지무지 큼. 앞에서 배운 Fast Polynomial Multiplication 과 거의 똑같이 하면 된다(!). Exercise. Jongwook Choi Fast Fourier Transform
예제 문제 (SRM 518 Div1 Hard) 두 n-length array A = (a0, · · · , an−1), B = (b0, · · · , bn−1) 가 있다. 이 때 A와 B의 xor-convolution C = A ⊕ B = (c0, · · · , cn−1) ck = i xor j=k aibj 를 구하시오. 단, n은 무지무지 큼. Jongwook Choi Fast Fourier Transform
예제 문제 (SRM 518 Div1 Hard) O(n log n) 에 도전. FFT의 아이디어를 이용해서 풉니다. 어떤 DFT F : Zn → Zn 를 찾자. F(A), F(B) 를 구한다. F(A), F(B) 를 pointwise 로 곱해서 F(A ⊕ B) 를 구한다. F(A ⊕ B) 에 F의 역변환을 끼얹어서 A ⊕ B 를 구한다. Jongwook Choi Fast Fourier Transform
예제 문제 (SRM 518 Div1 Hard) O(n log n) 에 도전. FFT의 아이디어를 이용해서 풉니다. 어떤 DFT F : Zn → Zn 를 찾자. F(A), F(B) 를 구한다. F(A), F(B) 를 pointwise 로 곱해서 F(A ⊕ B) 를 구한다. F(A ⊕ B) 에 F의 역변환을 끼얹어서 A ⊕ B 를 구한다. 그런 F 를 어떻게 찾지? Jongwook Choi Fast Fourier Transform
통밥의 정석 n = 2일 때를 가정해 보자. A = (a, b), B = (c, d) 라고 하면 A ⊕ B = (ac + bd, ad + bc) 이다. F(a, b) · F(c, d) = F(ac + bd, ad + bc) 가 되어야 한다. Jongwook Choi Fast Fourier Transform
통밥의 정석 n = 2일 때를 가정해 보자. A = (a, b), B = (c, d) 라고 하면 A ⊕ B = (ac + bd, ad + bc) 이다. F(a, b) · F(c, d) = F(ac + bd, ad + bc) 가 되어야 한다. F(a, b) = (a − b, a + b) 라고 가정해보자(???). Jongwook Choi Fast Fourier Transform
통밥의 정석 n = 2일 때를 가정해 보자. A = (a, b), B = (c, d) 라고 하면 A ⊕ B = (ac + bd, ad + bc) 이다. F(a, b) · F(c, d) = F(ac + bd, ad + bc) 가 되어야 한다. F(a, b) = (a − b, a + b) 라고 가정해보자(???). F(a, b) · F(c, d) = (a − b, a + b) · (c − d, c + d) Jongwook Choi Fast Fourier Transform
통밥의 정석 n = 2일 때를 가정해 보자. A = (a, b), B = (c, d) 라고 하면 A ⊕ B = (ac + bd, ad + bc) 이다. F(a, b) · F(c, d) = F(ac + bd, ad + bc) 가 되어야 한다. F(a, b) = (a − b, a + b) 라고 가정해보자(???). F(a, b) · F(c, d) = (a − b, a + b) · (c − d, c + d) = ((a − b)(c − d), (a + b)(c + d)) Jongwook Choi Fast Fourier Transform
통밥의 정석 n = 2일 때를 가정해 보자. A = (a, b), B = (c, d) 라고 하면 A ⊕ B = (ac + bd, ad + bc) 이다. F(a, b) · F(c, d) = F(ac + bd, ad + bc) 가 되어야 한다. F(a, b) = (a − b, a + b) 라고 가정해보자(???). F(a, b) · F(c, d) = (a − b, a + b) · (c − d, c + d) = ((a − b)(c − d), (a + b)(c + d)) = (ac − ad − bc + bd, ac + ad + bc + bd) Jongwook Choi Fast Fourier Transform
통밥의 정석 n = 2일 때를 가정해 보자. A = (a, b), B = (c, d) 라고 하면 A ⊕ B = (ac + bd, ad + bc) 이다. F(a, b) · F(c, d) = F(ac + bd, ad + bc) 가 되어야 한다. F(a, b) = (a − b, a + b) 라고 가정해보자(???). F(a, b) · F(c, d) = (a − b, a + b) · (c − d, c + d) = ((a − b)(c − d), (a + b)(c + d)) = (ac − ad − bc + bd, ac + ad + bc + bd) = ((ac + bd) − (ad + bc), (ac + bd) + (ad + bc)) Jongwook Choi Fast Fourier Transform
통밥의 정석 n = 2일 때를 가정해 보자. A = (a, b), B = (c, d) 라고 하면 A ⊕ B = (ac + bd, ad + bc) 이다. F(a, b) · F(c, d) = F(ac + bd, ad + bc) 가 되어야 한다. F(a, b) = (a − b, a + b) 라고 가정해보자(???). F(a, b) · F(c, d) = (a − b, a + b) · (c − d, c + d) = ((a − b)(c − d), (a + b)(c + d)) = (ac − ad − bc + bd, ac + ad + bc + bd) = ((ac + bd) − (ad + bc), (ac + bd) + (ad + bc)) = F(ac + bd, ad + bc) Olleh! Jongwook Choi Fast Fourier Transform
통밥의 정석 n = 4일 때에는? 좀 복잡한 듯. n = 2일 때 F(a, b) = (a − b, a + b) 였으니까, 느낌상 F(X Y ) = (F(X) − F(Y ) F(X) + F(Y )) 일 것 같다. (???) 세상은 원래 이렇게 아름다운 거에요 Jongwook Choi Fast Fourier Transform
통밥의 정석 n = 4일 때에는? 좀 복잡한 듯. n = 2일 때 F(a, b) = (a − b, a + b) 였으니까, 느낌상 F(X Y ) = (F(X) − F(Y ) F(X) + F(Y )) 일 것 같다. (???) 세상은 원래 이렇게 아름다운 거에요 사실 저 추측만 하면, 증명은 간단한 수학적 귀납법으로 어렵지 않다 (자세한 것은 editorial 참고). Jongwook Choi Fast Fourier Transform
역변환 F(X Y ) 가 주어질 때, X Y 를 찾을 수 있는가? 즉, X, Y 를 찾을 수 있는가? F(X Y ) = (F(X) − F(Y ) F(X) + F(Y )) 를 알고 있으므로, F(X) 와 F(Y ) 를 알 수 있다. 길이가 반으로 줄었으므로 재귀적으로 풀어서 X, Y 를 얻는다. X, Y 를 concatenate 시키면 끝. Jongwook Choi Fast Fourier Transform
FFT: 기타 응용 Fast Integer/Polynomial Multiplication Pattern Matching (Text Algorithms) Signal Processing Image Processing · · · Jongwook Choi Fast Fourier Transform