洛谷 P3803 【模板】多项式乘法(FFT)

题目链接:P3803 【模板】多项式乘法(FFT)

题意

给定一个 \(n\) 次多项式 \(F(x)\) 和一个 \(m\) 次多项式 \(G(x)\),求 \(F(x)\)\(G(x)\) 的卷积。

思路

FFT

又是一道 \(FFT\) 的模板题,不过用递归的 \(FFT\) 会超时。

代码

#include <bits/stdc++.h>
using namespace std;

const double PI = acos(-1);
typedef complex<double> Complex;
const int maxn = 3e6 + 10;

Complex a[maxn], b[maxn];
int m, n;
int bit = 2, rev[maxn];

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

void get_rev(){
    while(bit <= n + m) bit <<= 1;
    for(int i = 0; i < bit; ++i) {
        rev[i] = (rev[i >> 1] >> 1) | (bit >> 1) * (i & 1);
    }
}

void FFT(Complex *a, int op) {
    for(int i = 0; i < bit; ++i) {
        if(i < rev[i]) swap(a[i], a[rev[i]]);
    }
    for(int mid = 1; mid < bit; mid <<= 1) {  // 左右两部分的区间长度
        Complex wn = Complex(cos(PI / mid), op * sin(PI / mid));  // 单位复数根
        for(int j = 0; j < bit; j += mid<<1) {  // 一组一组处理
            Complex w(1, 0);
            for(int k = 0; k < mid; ++k, w = w * wn) {
                Complex x = a[j + k], y = w * a[j + k + mid];  // 蝴蝶操作
                a[j + k] = x + y, a[j + k + mid] = x - y;
            }
        }
    }
}

int main() {
    n = read(), m = read();
    for(int i = 0; i <= n; ++i) {
        a[i] = read();
    }
    for(int i = 0; i <= m; ++i) {
        b[i] = read();
    }
    get_rev();
    FFT(a, 1);
    FFT(b, 1);
    for(int i = 0; i <= bit; ++i) {
        a[i] *= b[i];
    }
    FFT(a, -1);
    for(int i = 0; i <= n + m; ++i) {
        printf("%d ", (int)(a[i].real() / bit + 0.5));
    }
    printf("\n");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wulitaotao/p/11537806.html