FFT P3803 [模板]多项式乘法

FFT(快速傅里叶变化) 可以加速求多项式乘法。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<queue>
#include<vector>

using namespace std;
typedef long long ll;
const int N = 4e6 + 105;
const int mod = 1e9 + 7;
const double Pi = acos(- 1.0);
const ll INF = 1e16;

inline int read() {
    char ch = getchar(); int x = 0, f = 1;
    while (ch < '0' || ch > '9') {
        if (ch == '-') f = -1;
	ch = getchar();
    }
    while ('0' <= ch && ch <= '9') {
	x = x * 10 + ch - '0';
	ch = getchar();
    } 
    return x * f;
}

struct complex {
    double x, y;
    complex (double xx = 0, double yy = 0) {x = xx, y = yy;}
} a[N], b[N];

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 l, r[N];
int len = 1;

void FFT(complex a[], int inv){
    for(int i = 0; i < len; ++ i)
	if(i < r[i]) 
	    swap(a[i], a[r[i]]);
	
    complex w, Wn, x, y;
	
    for(int mid = 1; mid < len; mid <<= 1){		
	Wn.x = cos(Pi / mid) , Wn.y = inv * sin(Pi / mid);
	for(int Size = mid << 1, L = 0; L < len; L += Size){	
	    w.x = 1, w.y = 0;
	    for(int i = 0; i < mid; i ++, w = w * Wn){   
		x = a[L + i], y = w * a[L + mid + i];
		a[L + i] = x + y;
		a[L + mid + i] = x - y;
	    }
	}
    }
}


int main()
{
    int n, m;
    n = read(), m = read();
    for(int i = 0; i <= n; ++ i) a[i].x = read();
    for(int i = 0; i <= m; ++ i) b[i].x = read();

    while(len <= n + m) len <<= 1, l ++;
    for(int i = 0; i < len; ++ i)
	r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));

    FFT(a, 1), FFT(b, 1);	
    for(int i = 0; i <= len; ++ i) a[i] = a[i] * b[i];
    FFT(a, -1);		
    for(int i = 0; i <= n + m ; ++ i){
        printf("%d ",(int)(a[i].x / len + 0.5));
    }
    return 0;
}

posted @ 2020-04-20 23:14  A_sc  阅读(119)  评论(0编辑  收藏  举报