전 주제와 다항 함수의 컨볼 루션을 생성 할 너무 많은 일을, 결과는 오늘 본질 최적화 된 회선 알고리즘을 이해했다.
우선 우리는에있는 바이너리 FWT 또는 간단한 예제로 시작합니다.
우리는 긍정적 인 FWT을 발견하거나 변환 $의 \ 모자를 찾고 {A} _j = \ sum_을 A_I의 $ {내가 일본에서 \}, 그 다음이 어떻게하는 것입니다,의 부분 집합이다?
우리는 그 $ A $ $ \ 모자 {A} $ 전송 행렬 $의 X의 $, 다음 가정
$$ (\ sum_ {J} X_ {I, J는} a_j) * (\ sum_는 {J} X_ {I, J} b_j) = \ sum_jX_ {I, J는} (\ sum_는 | a_sb_t {들 t는 J가 =} ) $$
그래서 $ a_sb_t $의 기여를 고려한다.
$$ X_ {I, S는} * {X_가 나는, t} = {X_ 난 S | t} $$
$ | 그래서 X- $ $의 각 행에 대해 $ X_s * X_t = X_ {t들}이
그리고 마지막으로, 역에 기인하는 것은 $ 곱한되는, X ^ 변환 {- 1} $, 우리는 역행렬을 알 수있는 경우에만 결정의 $ X $가 0이 아닌 $의 X의 $ 그렇게 두 줄 경우 동일하지 않습니다.
이에 따라, 우리는 단지 $ 0을 가정 $ X-한 후 $ X_ (이 간단한 때문에) {의 | t이} = 1 $와 $ X_s = X_t = 1 $ 상당이 도입 될 수있다 가.
$ $ N을 봐 = 8을 경우.
$$ X = \ 시작 pmatrix {} 1 0 0 0 0 0 0 0 \\ 1 1 0 0 0 0 0 0 \\ 1 0 1 0 및 0 0 0 0 \\ 1 1 1 1 0 0 0 0 \\ 1 0 0 0 1 0 0 0 \\ 1 1 0 0 1 1 0 0 \\ 1 0 1 0 1 0 1 0 \\ 1 1 1 1 1 1 1 1 \ 단부 pmatrix {} $$
법이 찾을 수있는 테이블을 쳐 가능
$$ X_ {I, J =} \ {prod_ K = 0} ^ {N-1} C_ {I [K ^ 2] J의 [K ^ 2]} $$
여기서 $ I [K ^ 2] $ $ I $ $ K 비트의 이진 표현 $.
$$ C = \ 시작 pmatrix {} 1 1 0 1 \\ \ {단부 pmatrix} $$
그럼 우리가 나누고 행렬 벡터 곱셈의 계산을 정복하는 방법을 알 수 있습니다. (예, 트리플 루프)
우리는 또한 FFT 매트릭스는 밖으로 쓸 수 있습니다.
$$ A = \ 시작 pmatrix {} \ omega_n ^ 0 \ omega_n ^ 0 \ ldots 단락 및 \ omega_n ^ 0 \ omega_n \\\ ^ 0 ^ 0 omega_n \ omega_n ^ 1 \ ldots 단락 및 \ omega_n ^ { N-2} \ omega_n ^ {N-1} \\\ vdots 및 \ vdots 및 \ ddots 및 \ ddots 및 \ ddots \\\ omega_n ^ 0 \ omega_n ^ {N-1} \ ldots 단락 및 \ omega_n ^ {(N-2) (N-1)} \ omega_n ^ {N-1 (N-1)} \ {단부 pmatrix} $$
즉 $ A_ {I, J =} \ omega_n ^ {} $ IJ 때문에
$$ ^ {- 1} = \ FRAC {1} {N} \ {시작 pmatrix} \ omega_n ^ {- 0} \ omega_n ^ {- 0} \ ldots 단락 및 \ omega_n ^ {- 0} \ omega_n ^ {- 0} \\\ omega_n ^ {- 0} \ omega_n ^ {- 1} \ ldots 단락 및 \ omega_n ^ {- (N-2)} \ omega_n ^ {- (N-1)} \\\ vdots 및 \ vdots 및 \ ddots 및 \ ddots 및 \ ddots \\\ omega_n ^ {- 0} \ omega_n ^ {- (N-1)} \ ldots 단락 및 \ omega_n ^ {- (N-2 ) (N-1)} \ omega_n ^ {- (N-1) (N-1)} \ {단부 pmatrix} $$
即 $ A ^ {- 1} _ {I, J =} \ {FRAC \ omega_n ^ {- IJ}} {m} $
UOJ272 노동 계급의 [2016] 석가장 칭화 훈련은 강했다
우리는 $ {B_ 세트 나, J는 $ {} I-1} $ $ $ F_i 천이 행렬 $ F_를 나타낸다.
정의 $ A \의 oplus B 형 $ 나타냅니다 원이 가산을 수행하지 하는 \의 ominus B 형 $가 나타내는 $ 원 뺄셈이 사임하지 . 쉬운이 두 작업 역 작업입니다 얻을 수 있습니다.
K FORALL $ \ B_가 K FORALL 수학적 유도 $의 \ 의해 얻어진 = B_ {I, J} $ {내가 oplus의 K, J를 \의 oplus의 K를 \}, B_가 ^ {난 oplus의 K, J \의 oplus의 K를 \} N = B_ {I, J, N} ^ $ 즉 $ B_ {I, J} ^ N = B_ {0, j 개의 \의 ominus I} ^ N 개의 $
$$ F_ {N, I} = \ sum_ {J} F_ {0, J} * B_ {J, I} ^ N = \ sum_ {J} F_ {0, J} * B_ {0, 난 J ominus \ } ^ N = \ sum_ {X \의 oplus의 Y = I *} F_X B_ {0, Y} ^ N $$
그래서 우리는 단순히 최초의 매트릭스와 $ B의 $의 행과 $ f_0 $을 필요로하는 것은 할 삼항에서 XOR의 회선 을.
우리는 먼저 이진 고려한다.
$$ C = \ {}를 시작 pmatrix 1 1 1 -1 \\ \ {단부 pmatrix} $$
(의미 $ C 형 $ 행렬은 상기 참조)
, XOR 회선 매트릭스 원이 무엇인지 (또는 자신 푸시 푸시 할 수 있습니다) 너무 감정적 이해 :
$$ C = \ 시작 pmatrix {} 1 1 1 1 \\ \ 오메가 및 \ 오메가 ^ 2 \\ 1 \ 오메가 ^ 2 \ 오메가 \ {단부 pmatrix} $$
$$ C ^ {- 1} = \ FRAC는 {1} {3} \ {pmatrix} 1 1 1 1 \\ \ 오메가 ^ 2 \ 오메가 \\ 1 \ 오메가 및 \ 오메가 ^ 2 \ 시작 끝 {pmatrix} $$
어디 $ \ 오메가 = \ FRAC {-1+ \의 SQRT {3} 내가} {2} $
그러나 $ \ SQRT는 {3} $ 동작 우리 얻을 매우 번잡하다, 또한 정밀도에 문제가 도심 \ 오메가 $, $ 1 , I 달러 대신에 $ 1, 즉 $로서 복소 표시 형태 + 오메가 $ a를 \ A B.
곱셈 $ a를 + 양방향 $ 곱셈 푸시를 밀어 같은 필요하지 않습니다.
$$ (A + B \ 오메가) (C + D의 \ 오메가) = AC + (BC + AD) \ 오메가 + BD (- \ 오메가 - 1) = (AC-BD) + (BC + 광고 BD) \ 오메가 $$
그 다음은 수행해야합니다.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #INCLUDE <cstdio> 2 #DEFINE RINT INT는 레지스터 3 사용 스페이스 성병; 4 의 typedef 긴 긴 LL; 5 CONST의 INT의 N = 531,441 ; 6 INT의 N, m, t, P, PO [ 13 ] cntx [N] cnty [N]; 7 인라인 공극 exgcd는 ( int로 A, INT의 B를, INT 및 X, INT 및 Y) { 도 8 의 경우 {X = (B!) 1 ; Y = 0 ; 반환 ;} 9 exgcd (B, A %의 B, Y, X); Y - = (LL) A / B * X; 10 } 11 구조체 착체 { 12 INT의 X, Y; 13 인라인 착체 ( INT X = 0 , INT Y = 0 ), X (X), Y (Y) {} 14 인라인 복합 운전자 + ( CONST 복합체 O) CONST { 반환 (착체 ((X + 소) % P는 Y + 오우) %의 P)} (15) 인라인 복합 운전자 - ( CONST 복합체 O) CONST { 창착체 ((X - 황소 +의 P) %의 P (Y - 오우 + P) %의 P)} (16) 인라인 복합 운전자 * ( CONST 복합체 O) CONST { 17 반환 착체 (((LL) X * 황소 %의 P - (LL)의 Y * 오우 % P의 +의 P) % P는, ((LL)의 Y * 황소 % 포인트 + (LL) × * 오우 % P - (LL)의 Y * 오우 % P + P) %의 P); 18 } 19 } A [N], B [N]; 20 인라인 복합 카스미 (복합체, INT의 b) { 21 복잡한 복합 입술 = ( 1 , 0 ); 22 일 동안 (b) { 23 일 경우 (B & 1 *) = 입술 입술에이; 24 A = A *의 a 및 25 B >> = 1 ; 26 } 27 리턴 입술; 28 } 29 인라인 복합 CALC1 ( CONST 복합체 a) { 반환 착체 ((p - (AY)의 +의 P) %의 - AY) % P는, (AX P)를} 30 인라인 복합 CALC2 ( CONST 복합체 a) { 반환 AY ((복잡한 - AX + P) % P는, (p - AX) %의 P)} (31) 인라인 공극 DFT (복합체 * A) { 32 대 (RINT 중간 = 1 , 중간 <N; 미드 * = 3) 33 대 (RINT의 J = 0 J <N; J + = 중간 * 3 ) 34 대 (RINT에서 K = 0 ; K <중간 k 번째 ++ ) { 35 복잡한 X = A [J + K, Y = A [J + K + 미드, Z = A [J + K + 중간 * 2 ]; 36 A [J + K] = X + Y + Z; 37 A [J + K + 미드] = X + CALC1 (Y) + CALC2 (z); 38 A [J + K + 중간 * 2 = X + CALC1 (z) + CALC2 (Y); 39 } 40 } 41 인라인 공극 IDFT (복합체 *A) { 42 대 (RINT 중간 = 1 , 중간 <N; 미드 * = 3 ) 43 대 (RINT의 J = 0 ; J <N; J + = 중간 * 3 ) 44 대 (RINT에서 K = 0 ; K <중간 ; 케이 ++ ) { 45 착체 X = A [J + K는, Y는 A [J + K + 미드, Z = A = J + K +를 중간 * 2 ]; 46 A [J + K] = X + Y + Z; 47 A [J + K + 미드] = X + CALC1 (z) + CALC2 (Y); 48 A [J + K + 중간 * 2 = X + CALC1 (Y) + CALC2 (z); 49 } 50 } 51 INT 트랜스 [ 13 ] [ 13 ]; 52 INT 의 main () { 53 는 scanf ( " % D % D % D " , m, t, P); 54 포 [ 0 ] = 1 ; 55 대 (RINT I = 1 ; I <= m; 내가 ++) PO [I] = (LL) PO [I - 1 ] * 3 ; (56) N = PO [m]; 57 대 (RINT I = 1 PO [I] = %; I <= m 내가 ++) P; 58 의 경우 (p ==의 1) { 59 대 (RINT I = 0 ; I <N은, 내가 ++) 풋 ( " 0 " ); 60 반환 0 ; 61 } 62 대 (RINT I = 0 ; I ++는, i가 N <) (scanf와를 " %의 D ' , A [I] .x를); 63 대 (RINT I = 0 ; I <= m; 내가 ++ ) 64 대 (RINT의 J = 0 ; i가 J <= m +; J ++)는 scanf ( " %의 D를 " 트랜스 [I] + J) ; 65 대 (RINT I = 0 ; I <N은, 내가 ++ ) { 66 cntx [I] = cntx [I / 3 ] + (I % 3 == 1 ); 67 cnty [I] = cnty [I / 3 ] + (I % 3 == 2 ); 68 B [I] = .x를 트랜스 [cntx [I] [cnty [I]; 69 // 의 printf ( "%의 D ', B [I] .x를); 70 } 71 // putchar ( '\ n')에; 72 DFT (A); DFT (B); (73) // (; 나는 <N; I = 0 RINT 난 ++) 미국의 printf ( "(%의 D %의 D) \ n", A [I] .x를하는이 [I] .Y); 74 // (; 나는 <N; I = 0 RINT 난 ++) 미국의 printf ( "(%의 D %의 D) \ n", B [I] .x를, B [I] .Y); (75) 에 대한(RINT I = 0 ; I <N은, 내가 ++) A [I] = A [i]는 * 카스미 (B [I], t); 76 IDFT (A); 77 INT의 INV, TMP; 78 exgcd (N, P, INV, TMP); 79 INV = (INV의 피 +) %의 P; 80 대 (RINT I = 0 ; I <N이 나는 ++ ) 81 의 printf ( " % D \ 없음 " (LL) A [I] .x와 INV *의 %의 P); 82 }