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;
}