fft

[largelargelarge{ ext{快速傅里叶变换}} ]

[;;;;;;;;;;;;;;By;tyq ]

介绍

这个算法干什么?——快速的计算多项式乘法

这个算法时间复杂度是多少——O(NlogN)

怎么搞?

一些定义

[ ext{多项式};A(x) = sum_{i=1}^{N}a_ix^i ]

[ ext{多项式A和B的乘积C};C(x) = sum_{i=1}^{2 imes N}c_i imes x^i ]

[其中c_k=sum_{i+j=i,0 leq i,j < n}a_i imes b_j imes x^k ]

[ ext{(虚数单位)} i = sqrt{-1} ]

[ ext{N次单位根}omega_n^j = e^{frac{2ijpi}{n}}=(omega_n)^j ]

[w_n=e^{frac{2ipi}{n}}{} ]

接下来说在怎么fft

引理

[(omega_n^i)^2 ext{所构成的集合}=omega_{frac{n}{2}}^i ]

[ ext{证明:};;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ]

[ ext{带入定义易证} ]

坑以后填

#include<complex>
#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std ;

#define complexs complex<double>
#define N 2621450
const double Pi = acos(-1) ;
int limit = 1 ;
int r[N] ;

void fft(complexs* A, int type) {
    for (int i = 0; i < limit; i++)
        if (i < r[i]) swap(A[i], A[r[i]]);
    for (int mid = 1; mid < limit; mid <<= 1) {
        complexs Wn( cos(Pi / mid) , type * sin(Pi / mid) ); 
        for (int R = mid << 1, j = 0; j <limit; j += R) { 
            complexs w(1, 0); 
            for (int k = 0; k < mid; k++, w = w * Wn) {
                complexs x = A[j + k], y = w * A[j + mid + k];
                A[j + k] = x + y;
                A[j + mid + k] = x - y;
            }
        }
    }
}
complexs A[N],B[N] ;
int main(){
	int n,m,l=0 ; scanf("%d%d",&n,&m) ;
	for(limit=1;limit<=n+m;limit<<=1) ++l;
	for (int i = 0; i < limit; i++) 
		r[i]=(r[i>>1]>>1)|((i&1)<<(l-1)) ;
	int x ;
	for(int i=0;i<=n;++i) {scanf("%d",&x) ; A[i]=complexs(x,0) ;}
	for(int i=0;i<=m;++i) {scanf("%d",&x) ; B[i]=complexs(x,0) ;}
	fft(A,1) ; fft(B,1) ;
	for(int i=0;i<limit;++i) A[i] = A[i]*B[i] ;
	fft(A,-1) ;
	for(int i=0;i<=n+m;++i){
		printf("%d ",int(A[i].real()/limit+0.5)) ;
	}
	puts("") ;
	return 0 ;
}
原文地址:https://www.cnblogs.com/tyqtyq/p/10604355.html