FFT entry

FFT entry

background knowledge

FFT is a fast solution of the product of two polynomial algorithms, time complexity is excellent \ (O (nlogn) \) , the main idea is to divide and conquer.

FFT = Fast = Fast DFT Discrete Fourier Transform

Coefficients of the polynomial representation of the presence of point values and notation, the two can be interchangeable;
n-times the highest order polynomial is n, there are (n + 1) th coefficient, requires (n + 1) th to represent distinct points

FFT main ideas

  1. Pre-filled high-order 0, so that the final number of coefficients greater than (N + M); (N order polynomial and a polynomial of degree M)
  2. It represents a coefficient represented by point value is converted into (x coordinate is substituted into \ (x = (w_n ^ 0, ... w_n w_n ^. 1. 1-n-^ {} \) ); where is the number of n-needed point; this can be achieved through the partition \ (O (nlogn) \)
  3. Point value indicates multiplication method, the complexity of the \ (O (n) \)
  4. Point value converted into coefficients showing indicates that the problem may be to Step 1 Statute

Here we will focus on 3 points

Points

Polynomial coefficients represents a value converted to a point represented

Note polynomial \ (A (X) = a_0 + a_1x + ... + a_2x A_ ^ {n-2-X ^ {}. 1. 1-n-} \) , \ (A (X) \) a \ (N- 1 \) order polynomial, we need \ (n \) points to represent. We choose the complex domain \ (w_n ^ i = e ^ {i * \ frac {2 \ pi} {n}} = cos (\ frac {2i \ pi} {n}) + i sin (\ frac {2i \ pi} {n}) \ quad i = 0,1,2, .. n-1 \) such points i.

They satisfy two properties:

  1. \(w_n^k = -w_n^{k+\frac{\pi}{2}}\)
  2. \ (^ w_n K = {Nd} W_ KD ^ {} \) , assuming \ (kd, nd \) are integers

The two pieces of the complex nature of the unit circle painted on what can be known.

Suppose \ (n-2 = ^ T \) , in fact, will be pre-treated to step 0 \ (2 ^ T \) ; we \ (A (x) \) according to the position of the coefficient divided into two parts, i.e., :
\ (A1 (X) = a_0 + .. + a_2x A_ ^ {n-2-X ^ {n-2}} = 2-\ sum_ {I = I = {0} ^ \ FRAC {n-2} {} - 1} a_ {2i} x ^ {2i} \)

\(A2(x) = a_1+a_3x^3+...a_{n-1}x^{n-1} = \sum_{i=0}^{i=\frac{n}{2}-1}a_{2i+1}x^{2i+1} = x\sum_{i=0}^{i=\frac{n}{2}-1}a_{2i+1}x^{2i}\)

\(A(x)=\sum_{i=0}^{n-1}a_ix^i = A1(x)+A2(x)\)

Notice \ (A1 (x), A2 (x) \) Although the coefficient reduced by half, but need to bring a \ (x \) is still \ (n \) key;
suppose we \ (x = w_n ^ k \) substitution \ (A1 (the X-) \) (substituting \ (A2 (x) \) is the same), then:

\(A1(w_n^k)=\sum_{i=0}^{i=\frac{n}{2}-1}a_{2i}w_n^{2ki}=\sum_{i=0}^{i=\frac{n}{2}-1}a_{2i}w_{\frac{n}{2}}^{ki} \quad k=0,1,2....n-1\),(根据性质2)

Again changes, k is divided into first half and second half processing:

\ (A1 (w_n ^ k) = \ sum_ {i = 0} ^ {i = \ frac {n} {2} -1} a_ {2i} w _ {\ frac {n} {2}} ^ {ki} \ Quad K = 0,1,2, \ FRAC {n-2} {-1} \) , the first part referred to as

\ (A1 (w_n ^ {k + \ frac {n} {2}}) = - \ sum_ {i = 0} ^ {i = \ frac {n} {2} -1} a_ {2i} w _ {\ frac {n} {2}} ^ {ki} \ quad k = 0,1,2, \ frac {n} {2} -1 \) the latter half (the nature of the use of 1)

It can be seen we obtain \ (A1 (w_n ^ k) \) at the same time has the \ (A1 (w_n ^ {k + \ frac {n} {2}}) \) seek out, so solving \ (A1 (w_n ^ k) \) scale relative to \ (a (x) \) will order a half, how nice results ( \ (A2 (the X-) \) empathy).

So \ (T (n-) = 2 * (n-/ 2) + O (n-) \) , since \ (X \) have \ (n-\) kinds of values, so by \ (A1 (x) \) and \ (A2 (x) \) determined \ (A (x) \) requires \ (O (n) \) time

Recursive wording

void FFT(Complex* a,int len,int opt){
    if(len==1)
        return;
    Complex* a0=new Complex[len/2];
    Complex* a1=new Complex[len/2];
    for(int i=0;i<len;i+=2){
        a0[i/2]=a[i];
        a1[i/2]=a[i+1];
    }
    FFT(a0,len/2);
    FFT(a1,len/2);
    Complex wn(cos(2*Pi/len),opt*sin(2*Pi/len));
    Complex w(1,0);
    for(int i=0;i<(len/2);i++){
        a[i]=a0[i]+w*a1[i];
        a[i+len/2]=a0[i]-w*a1[i];
        w=w*wn;
    }
    delete[] a0;
    delete[] a1;
}

Point represents a value converted into coefficients (some referred to as IDFT)

Consider the coefficient matrix representation of the point values:

\[ \begin{bmatrix} w_n^0 & w_n^{0*1} & w_n^{0*2} & ... &w_n^{0*{n-1}} \\ w_n^{1*0} & w_n^{1*1} &w_n{1*2} & ... & w_n^{1*{n-1}} \\ ... & \\ w_n^{{(n-1)}*0} & w_n^{{(n-1)}*1} & w_n^{(n-1)*2} & .. & w_n^{{(n-1)}*{(n-1)} } \end{bmatrix} \begin{bmatrix} a0 \\ a1 \\ .. \\ a_{n-1} \end{bmatrix} = \begin{bmatrix} y0 \\ y1 \\ .. \\ y_{n-1} \end{bmatrix} \]

We referred to as \ (W is \ CDOT the Y = A \) ; then the value is the transform coefficients from the point \ (^ W is A = {-}. 1 \ CDOT the Y \) .
Given below without proof \ (^ W is {-}. 1 = \ n-FRAC {} {}. 1 [W ^ {-} ij of] \) , \ (W ij of ^ {} \) represents \ (W is \) element in row i and column j. After taking the inverse matrix of each complex i.e. W is the inverse of the original matrix W \ (\ FRAC {{n-1}} \) . Such Step 3 to Step 1 to the Statute

FFT Optimization

From iteration recursive form to form directly given detailed notes code may luogu3803 cross title

Iterative version

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int MAXN=1e7+10;
const double Pi=acos(-1.0);
struct complex{
    double x,y;
    complex (double xx=0,double yy=0){x=xx,y=yy;}
}a[MAXN],b[MAXN];
complex operator + (complex a,complex b){ return complex(a.x+b.x , a.y+b.y);}
complex operator - (complex a,complex b){ return complex(a.x-b.x , a.y-b.y);}
complex operator * (complex a,complex b){ return complex(a.x*b.x-a.y*b.y , a.x*b.y+a.y*b.x);}//复数的运算那部分 
int N,M;
int l,r[MAXN];
int limit=1;
void fft(complex *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)//待合并区间的中点,其实(mid<<1)是要求的DFT(某一层)的长度
    {
        complex Wn( cos(Pi/mid) , type*sin(Pi/mid) ); //单位根 本质是 2*PI/(2*mid)
        for(int R=mid<<1,j=0;j<limit;j+=R)//R实际是步长,即同一层每组要处理的起始位置
        {
            complex w(1,0);//幂  单位1
            for(int k=0;k<mid;k++,w=w*Wn)//枚举左半部分 
            {
                 complex x=A[j+k],y=w*A[j+mid+k];//蝴蝶效应(只是装x),实际上什么有没有就是减少一次y的计算(复数乘法)
                A[j+k]=x+y;                                   // A[k]
                A[j+mid+k]=x-y; //mid即位推导中的2/n;此处可以看作 A[k+2/n]
            }
        }
    }
}

int main()
{
    //n次多项式由(n+1)个系数,有n个复数解,最高次为n
    scanf("%d",&N);scanf("%d",&M);
    for(int i=0;i<=N;i++) scanf("%lf",&a[i].x);//复数域的实数部分
    for(int i=0;i<=M;i++) scanf("%lf",&b[i].x);
    while(limit<=N+M) limit<<=1,l++; //最高次为(N+M) 所以至少需要(N+M+1)个点值;为了fft的方便扩展成 2^l(2^l>(N+M)) 高次皆为0
    for(int i=0;i<limit;i++)
        r[i]= ( r[i>>1]>>1 )| ( (i&1)<<(l-1) ) ; //位逆置 r[i>>1]>>1 能反转前面的l-1 位; 然后将末尾的位或到首位即可
    // 在原序列中 i 与 i/2 的关系是 : i可以看做是i/2的二进制上的每一位左移一位得来
    // 那么在反转后的数组中就需要右移一位,同时特殊处理一下复数 
    fft(a,1);// fft保留的是x= w_{limit}^1, w_{limit}^2 .... w_{limit}^{limit}是的取值
    fft(b,1);
    for(int i=0;i<=limit;i++) a[i]=a[i]*b[i]; //点值表示法的优秀乘法
    fft(a,-1);  //点值表示法到系数表示法,会涉及到逆矩阵,所以fft后还有一个1/limit (limit 实际上是矩阵的行列式(n*n的满秩矩阵才有行列式))
    for(int i=0;i<=N+M;i++)
        printf("%d ",(int)(a[i].x/limit+0.1));//直接用实数域
    return 0;
}

reference

blog0 blog1 blog2 blog4

Guess you like

Origin www.cnblogs.com/fridayfang/p/11094045.html
FFT