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.
결정되면 유일하게 결정된다 (Lagrange’s Interpolation). C(z) 의 degree 는 (at most) 2n − 2 이므로, 서로 다른 2n − 1 개의 점에 대해 C 의 함수값만 알면 되겠다. Jongwook Choi Fast Fourier Transform
결정되면 유일하게 결정된다 (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
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
· · · + 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
· · · + 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
방법은? 즉, 최대 2n차 다항식 C에 대해 C(ω0), C(ω1), · · · , C(ω2n−1) 를 알고 있을 때 (ω2n = 1) C의 계수 c0, c1, · · · , c2n−1 를 구하려면 어떻게 하는가? Jongwook Choi Fast Fourier Transform
를 DFT 하는데 ω를 ω−1 로 replace 하고 최종 결과를 n 으로 나누면 (a0, a1, a2, · · · , an−1) 이 얻어진다. 즉 FFT 함수가 있으면 역변환 하는것도 바로 된다. O(n log n) Jongwook Choi Fast Fourier Transform
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
· , 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
· , 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
= (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
도전. 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
도전. 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
(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
(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
(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
(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
(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
(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
= 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
찾을 수 있는가? 즉, 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