HDU_1402_A * B Problem Plus(FFT快速傅里叶变换)

题型:数论


题意:计算A*B


分析:

数字长度达50000,朴素的高精度,复杂度为O(n^2).

引出FFT(快速傅里叶变换)

FFT能够在nlog(n)时间完成多项式相乘的计算。

设多项式:

HDU_1402_A * B Problem Plus(FFT快速傅里叶变换)_第1张图片(1)

朴素计算A*B,需要O(n^2)复杂度

对于多项式,除了上式这样比较普遍的表示方法之外,还可以用类似于二维平面坐标的方式表示。

对于A,有(x0,a0)                 对于B,有(x0,b0)

                 (x1,a1)                                  (x1,b1)

                    ...                                           ...

                 (xn,an)                                  (xn,bn)                                                        (2)

可以唯一表示一个多项式,其中ai = A(xi)   bi = B(xi)

那么求出A*B为  (x0,a0*b0)

                          (x1,a1*b1)

                                ...

                          (xn,an*bn)

只需要O(n)的时间

FFT实际上是这样的过程:

①DFT将(1)转换为(2)   ---------------->离散傅里叶变换
②O(n)计算
③IDFT将(2)转换为(1) ----------------->离散傅里叶逆变换

关于FFT的具体实现,就不再详解了。


代码:

#include
#include
#include
#include

using namespace std;

const int M = 5e4+10;
struct Complex {///复数结构体
    double x,y;///实部和虚部 x+yi
    Complex(double _x=0,double _y=0) {
        x=_x;
        y=_y;
    }
    friend Complex operator -(const Complex &a,const Complex &b) {
        return Complex(a.x-b.x,a.y-b.y);
    }
    friend Complex operator +(const Complex &a,const Complex &b) {
        return Complex(a.x+b.x,a.y+b.y);
    }
    friend Complex operator *(const Complex &a,const Complex &b) {
        return Complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
    }
};
class FFT {///快速傅里叶变换
    Complex u,t;
    void change(Complex y[],int len) { ///len必须是2的幂
        for(int i=1,j=len>>1,k; i>1;
            while(j>=k) {
                j-=k;
                k>>=1;
            }
            if(j>1;
                for(int k=j; k=0;i--){
            printf("%d",sum[i]);
        }
        puts("");

    }

    return 0;
}


                 (x0,a0)

你可能感兴趣的:(ACM)