算法导论30(多项式与快速傅里叶变换)

A(x)=a0+a1x++an1xn1=j=0n1ajxj(a0+a1x++an1xn1)(b0+b1x++bn1xn1)=a0b0+(a0b1+a1b0)x++an1bn1x2n2=j=02n2(k=0jakbjk)xj(aj=bj=0,jn)

30.1 多项式的表达

系数表达: (a0,a1,,an1)

点值表达: {(x0,y0),(x1,y1),,(xn1,yn1)}(yk=A(xk),0kn1)

求值(系数表达转换为点值表达, O(n2) ):
霍纳准则: A(x0)=a0+x0(a1++x0(an2+x0an1))

插值(点值表达转换为系数表达, O(n2) ):
拉格朗日公式: A(x)=k=0n1ykjk(xxj)jk(xkxj)

30.2 DFT与FFT

wn=1w=w0n,w1n,,wn1n(wn=e2πi/n)yk=A(wkn)=j=0n1ajwkjn(0kn1)

y=(y0,y1,,yn1) a=(a0,a1,,an1) 的离散傅里叶变换(DFT)。

n=2kA[0](x)=a0+a2x++an2xn/21A[1](x)=a1+a3x++an1xn/21A(x)=A[0](x2)+xA[1](x2)

0kn/21yk=y[0]k+wkny[1]k=A[0](wkn/2)+wknA[1](wkn/2)=A[0](w2kn)+wknA[1](w2kn)=A(wkn)yk+n/2=y[0]kwkny[1]k=A[0](wkn/2)wknA[1](wkn/2)=A[0](w2k+nn)+wk+n/2nA[1](w2k+nn)=A(wk+n/2n)

const double PI=3.141592654;

class Complex
{
public:
    Complex(double x=0,double y=0):a(x),b(y){}
    friend Complex operator+(Complex x,Complex y)
    {
        return Complex(x.a+y.a,x.b+y.b);
    }
    friend Complex operator-(Complex x,Complex y)
    {
        return Complex(x.a-y.a,x.b-y.b);
    }
    friend Complex operator*(Complex x,Complex y)
    {
        return Complex(x.a*y.a-x.b*y.b,x.a*y.b+x.b*y.a);
    }
    double a,b;
};

//递归
vector<Complex> recursiveFFT(vector<Complex> a)
{
    int n=a.size();
    if(n==1)return a;
    Complex wn(cos(2*PI/n),sin(2*PI/n)),w(1,0);
    vector<Complex> a0,a1,y0,y1,y;
    for(int i=0;i<n;i+=2)a0.push_back(a[i]);
    for(int i=1;i<n;i+=2)a1.push_back(a[i]);
    y0=recursiveFFT(a0);
    y1=recursiveFFT(a1);
    for(int k=0;k<=n/2-1;++k)
    {
        y[k]=y0[k]+w*y1[k];
        y[k+n/2]=y0[k]-w*y1[k];
        w=w*wn;
    }
    return y;
}

T(n)=2T(n/2)+Θ(n)=Θ(nlogn)

30.3 高效FFT实现

//蝴蝶操作
for(int k=0;k<=n/2-1;++k)
{
    Complex t=w*y1[k];
    y[k]=y0[k]+t;
    y[k+n/2]=y0[k]-t;
    w=w*wn;
}

//位逆序置换
int rev(int k,int n)
{
    int k0=0,m=log((double)n)/log((double)2);
    for(int j=0;j<m;++j)
    {
        if(k&(1<<j))k0+=(1<<(m-1-j));
    }
    return k0;
}

void bitReverseCopy(vector<Complex> a,vector<Complex> &A)
{
    int n=a.size();
    for(int k=0;k<=n-1;++k)A[rev(k,n)]=a[k];
}

//迭代
vector<Complex> iterativeFFT(vector<Complex> a)
{
    vector<Complex> A;
    bitReverseCopy(a,A);
    int n=a.size();
    for(int s=1;(1<<s)<=n;++s)
    {
        int m=(1<<s);
        Complex wm(cos(2*PI/m),sin(2*PI/m));
        for(int k=0;k<=n-1;k+=m)
        {
            Complex w(1,0);
            for(int j=0;j<=m/2-1;++j)
            {
                Complex u=A[k+j],t=w*A[k+j+m/2];
                A[k+j]=u+t;
                A[k+j+m/2]=u-t;
                w=w*wm;
            }
        }
    }
    return A;
}

你可能感兴趣的:(算法导论30(多项式与快速傅里叶变换))