FFT && 复数重载

复数重载 与 FFT

1.复数重载:

重载了复数的运算,即重载了复数的加减乘以及赋初值。

struct Complex{          //复数的重载
    double r,i;
    IL Complex(){r = 0; i = 0;}
    IL Complex(RG double a,RG double b){r = a; i = b;}
    IL Complex operator +(Complex B){ return Complex(r+B.r,i+B.i); }
    IL Complex operator -(Complex B){ return Complex(r-B.r,i-B.i); }
    IL Complex operator *(Complex B){
        return Complex(r*B.r-i*B.i , r*B.i+i*B.r);
    }
};

其中\(f.r\)为实部 ,\(f.i\)为虚部。

2.FFT算法:

计算多项式\(f_1\)*\(f_2\) == \(f_3\)的算法,
时间复杂度\(O(n\ logn)\) , 空间最好开\(O(3n)\)\(O(4n)\)左右;

Complex f1[_],f2[_],X,Y; int f3[_];  //f3储存卷积的系数.
const double PI = acos(-1);

IL void Init(){         //读入数据,预处理.
    cin >> n >> m;
    for(RG int i = 0; i <= n; i ++)cin >> f1[i].r;
    for(RG int j = 0; j <= m; j ++)cin >> f2[j].r;  //读入两个多项式
    m += n; l = 0;
    for(n = 1; n <= m; n<<=1)l++;
    //此时m保存卷积的长度,n等于二进制补全后 数列长度+1 .       
    //Rader预处理:
    for(RG int i = 0; i < n; i ++)R[i] = (R[i>>1]>>1) | ((i&1)<<(l-1));
}

IL void FFT(Complex *P , int opt){
    for(RG int i = 0; i < n; i ++)
        if(i < R[i]) swap(P[i] , P[R[i]]);   //Rader 排序
    for(RG int i = 1; i < n; i<<=1){    
        Complex W(cos(PI/i),opt*sin(PI/i));  
        for(RG int p = i<<1 , j = 0; j < n; j += p){
            Complex w(1,0);
            for(RG int k = 0; k < i; k ++,w = w*W){
                X = P[j + k] , Y = w*P[j + k + i];
                P[j + k] = X + Y;    P[j + k + i] = X - Y;
            }
        }
    }
    if(opt == -1) for(RG int i = 0; i < n; i ++)P[i].r /= n;
}

int main(){   
    Init();

    //计算f1*f2
    FFT(f1,1); FFT(f2,1);
    for(RG int i = 0; i <= n; i ++)f1[i] = f1[i]*f2[i];
    FFT(f1,-1);

    //最后结果存在f1中.
    for(RG int i = 0; i <= m; i ++)f3[i] = (int)(f1[i].r+0.5));
    return 0;
}

posted @ 2018-01-25 23:07  Guess2  阅读(372)  评论(0编辑  收藏  举报