최근 보트 투어 배 미친, 좋은 기분 ~
특정 파생이 참조 : 후 토끼 - 학생들이 FFT를 이해할 수있다! ! ! (물론 쓰기,하지만이 처음으로 학생들은 0.0 이해하지 못했다)
핵심 요소를 요약
~ 제 1 부 ~ 다항식 피벗 포인트 값을 나타냅니다
$ 2 전원 원래 다항식 $ A는 (X) $ $으로 보완 재귀 분할 하였다
즉, 현재 레이어의 $ 다항식 B (x)는 $, $ N $의 숫자로 설정한다 : $ B를 (X) = + b_0 B_ {1}, X + B_ {2} X ^ {2} + ... + B_ {N-1}, X ^ {N-1} $
이것은 제 패리티 계수에 따라 두 다항식으로 분할
\ [B_0 (X) = b_0 + + b_2x b_4x ^ 2 + ... + B_ {N-2} X ^ {\ FRAC {N} {2} -1} \]
\ [B_1 (X) = B_1 b_3x + + b_5x ^ 2 + ... + B_ {N-1}, X ^ {\ FRAC {N} {2} -1} \]
이것은 $ B 일 수있다 (X)는 $ 재 나타낸다 : $의 B (X) = B_0 (X ^ 2) + xB_1 (X ^ 2) $
우리는 복소 평면 대입 포인트 단위 원은 $의 B를 (\ 오메가 ^ {1} _ {N}) $, ..., $ B (\ 오메가 ^ {N} _ {N}) $ 값을 부여 할
때문에 단위 원에 $ \ 오메가 $이므로 $ \ 오메가 ^ 2051-N \ cdot \ 오메가 ^ j_n = \ 다음 $ 0 \ 당량 I <\ FRAC {N} {2} $ 거기 [여기 복잡한 연산 법을 사용하는 경우 오메가 ^ _n $ {난 J +} $ 2 $에서 $ N- $ 배수이므로 $ \ 오메가 ^ 2051-N = \ 오메가 ^ {\ FRAC {I}를 {2}} _ {\ FRAC {N} {2} } $]
\ 시작 B (\ 오메가 ^ 2051-N) = B_0 {* 정렬} ((\ 오메가 ^ 2051-N) ^ 2) + \ 오메가 ^ i_nB_1 ((\ 오메가 ^ 2051-N) ^ 2) \\ & = B_0 (오메가 \ ^ {2I} _n) + \ 오메가 ^ i_nB_1 (\ 오메가 ^ {2I} _n) \\ & = B_0 (오메가 \ ^ 제가 _ {\ FRAC {N} {2}}) + \ 오메가 ^ i_nB_0 (\ 오메가 ^ I_ {\ FRAC {N} {2}}) \ 단부 {} * 정렬
단위 원에 나머지 절반 후 별도로 여기 [복잡한 연산 법이있다 : $ N- $는 $의 $ 2의 배수이기 때문에 너무 $ \ 오메가 ^ {내가 + \ FRAC {N} {2}} _ N = - \ 오메가 ^ $ 2051-N]
\ 시작 {정렬 *} B (\ 오메가 ^ {내가 + \ FRAC {N} {2}} _ N) = B_0 ((\ 오메가 ^ {내가 + \ FRAC {N} {2}} _ N) ^ 2) + \ 오메가 ^ {난 + \ FRAC {N} {2}} _ nB_1 ((\ 오메가 ^ {I + \ FRAC {N} {2}} _ N) ^ 2) \\ & = B_0 (\ 오메가 ^ {2I + N} _n ) - \ 오메가 ^ i_nB_1 (\ 오메가 ^ {2I + N} _n) \\ & = B_0 (오메가 \ ^ I _ {\ FRAC {N} {2}}) - \ 오메가 ^ i_nB_0 (\ 오메가 ^ I _ {\ FRAC {N} {2}}) \ 단부 {} * 정렬
이 층은 우리가 $ B를 계산 (\ 오메가 ^ 0_n)은 $, ..., $ B는 (\ 오메가 ^ {N-1} _는 {N-1}) $ $ B_0는 문제가 산출 한진다 (\ 오메가 ^ 0 _ {\ FRAC {N} {2}}) $, ..., $ B_0 (\ 오메가 ^ {\ FRAC {N} {2} -1} _ {\ FRAC {N} {2} }) $, $ B_1 (\ 오메가 ^ 0 _ {\ FRAC {N} {2}}) $, ..., $ B_1 (\ 오메가 ^ {\ FRAC {N} {2} -1} _ {\ FRAC {N} {2}}) $
따라서, 총 복잡도는 $ O (N logN)은 $
다항식의 ~ 2 부 ~ 소수점 값 전달 계수
$ 여러 원시 다항식 설정하면 A (X) = a_0 + + a_1x a_2x ^ 2 + ... + A_ {N-1}, X ^ {N-1} $, $ 2 $ 11 항에있어서, 용어의 전력으로서 $ n 개의 $
각각 $ \ 오메가로 치환 ^ 0_n $, $ \ 오메가 ^ 1_n $, ..., 오메가 $ \ ^ {N-1} _n $, GET $ y_i = A (\ 오메가 ^ 2051-N) $, $ I = 0 1, ..., N-1 $, $, 즉 N- 포인트 값 $ 상기에서 얻어진
令 $ B (X) = + y_0 y_1x y_2x + ^ 2 + ... + Y_ {N-1}, X ^ {N-1} $
오메가 \ ^ - {1} _n $, ..., $ {- (N-1)} 다음 $ \ 오메가 ^ 0_n $, $ \ 오메가 ^로 치환 하였다 _ N $으로 계산 (생략)을 수득 $ A_I = \ FRAC {B (\ 오메가 ^ {- I} _n)} {N} $, $ I = 0,1, ..., N-1 $
다음의 코드에 따라이 아이디어는 (다항식 계수 뒤쪽 다항식 계수를 달성하기 위해 피벗 포인트 등) 작성된
지표의 갱스터 배열은 정말 편리한 사용
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#INCLUDE <cstdio> #INCLUDE <복합체> #INCLUDE <cmath> #INCLUDE <CString을> #INCLUDE <알고리즘> 사용 스페이스 성병; 복합 타입 정의 < 더블 > CP; CONST의 INT의 N = 100005 ; CONST 이중 PI ACOS = (- 1.0 ); 인라인 CP 오메가 ( INT의 X, INT의 N, INT의 REV) { 경우 (REV) X = - (X); 리턴 CP (COS (X * 2 * 파이 / (이중 ) N), 죄 (X * 2 * PI / ( 더블 ) N)); } CP의 TMP [N]; 보이드 FFT (CP * A, int로 N, INT의 REV) { 경우 (N == 1 ) 복귀 ; 위한 ( int로 I = 0 ; I <N은, 내가 ++ ) TMP가 [I] = A [I]; 위한 ( int로 난 = 0 ; i가 N / < 2 ; i가 ++ ) { A [I]를 TMP가 = [내가 * 2 ]; A [N / 2 + i가] = TMP [내가 *2 + 1 ]; } FFT (a, N / 2 , REV); FFT (a + N / 2 , N / 2 , REV); 위한 ( int로 난 = 0 ; i가 N / < 2 ; i가 ++ ) { CP X = 오메가 (I, N, 레브); TMP [내가] = A [i]는 + X * A [N / 2 + I]; TMP는 [N / 2 + i가] = A [i]를 -x * A [N / 2 + I]; } 에 대해 ( int로 I = 0 ; I <N은, 내가 ++ ) A [i]를= TMP [I]; } int로 N; A [N] CP; INT 의 main () { // freopen을 ( "input.txt를", "R", 표준 입력); scanf와 ( " %의 D ' , N); 위한 ( int로 I = 0 ; I <N이 나 ++ ) { INT (X)를; scanf와 ( " %의 D ' , X); A [I] = CP (( 더블 ) X, 0 ); } INT SZ = 1 ; 반면 (SZ < N) SZ<< = 1 ; N = SZ; FFT (a, N, 0 ); FFT (a, n은, 1 ); 위한 ( int로 I = 0 ; I <N이 나 ++ ) 의 printf를 ( " %의 .2lf " , A [i]를 .real () / ( 더블 ) N)을; 의 printf ( " \ n을 " ); 반환 0 ; }
~ 3 부 ~ 두 가지 간단한 최적화
비 재귀 :
제 1 부분의 순환, 즉 직접 수행에 $ A [i]를 $ 패리티 패킷 교환
여기서 과거 위치이다 이백이십일쌍 결국 $ 1 $ ($ $ 001)와 상호 교환 적으로 사용되는 경우, N = $ 8 $은 $ 4 $ ($ $ 100) -이 중
즉 두 진 절환 위치는 전후 반전
$ tmp를 [I] $ 배열 분리 :
각각 $ I $위한 순환 루프의 두 번째 부분 만 TMP가 [I]가 $, TMP 달러 $를 사용하여 [N / 2 + i]는 $는 A [N / A [I]을 $ $ $ 2 + I] $
그래서 현재 $ I $를 변경하지 아니 후 효과 대신 $ TMP의 임시 변수를 사용하는 것을 고려 [I] $ 배열
따라서,이 재귀하지 않고 기록 할 수 있고, $ TMP [I] $ 배열 FFT $ () 함수 $
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
보이드 FFT는 CP (* a는, int로 , N 의 INT 레브) { 위해 ( int로 I = 0 ; I <N은, 내가 ++ ) { INT를 NXT = 0 ; 대 ( INT의 J = 1 ; J <= N; J << = 1 ) 의 경우 (I 및 J) NXT + = N / 2 / J; 경우 (NXT> I) 스왑 (a [i]를, A [NXT]); } 에 대해 ( int로 난 = 2 ; i가 N = <나는 << = 1 ) 대 ( INT의 J = 0 ; J <J + N = I) 대 ( INT에서 K = 0 ; K <입 / 2 ; ++ 케이 ) { CP X = 오메가 (K, I, REV); CP의 B0 B1 = A [J + K] = A [i가 / 2 + J + K]; A [J + K] = B0가의 + X * B1; A [내가 / 2 + J + K]는 B0-X에서의 * = B1 단계; } }
FFT 컨볼 루션 계산
(계속 예정)