多项式乘积(fft)

Posted jpphy0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多项式乘积(fft)相关的知识,希望对你有一定的参考价值。

问题

  • 设多项式 A ( x ) 、 B ( x ) 、 C ( x ) A(x)、B(x)、C(x) A()()C() 满足 A ( x ) = B ( x ) ∗ C ( x ) A(x)=B(x)*C(x) A()=()C() ,且给定了 B ( x ) 、 C ( x ) B(x)、C(x) B()C() 的系数。
  • A ( x ) A(x) A()的系数。
  • 输入样例:
    1
    3 3 // B(x)、C(x)的最高次
    1 1 1 1 // B(x)的系数
    1 1 1 1 // C(x)的系数
  • 输出样例
    1 2 3 4 3 2 1

分析

  • fft

代码

#include <bits/stdc++.h>
using namespace std;
const double DFT = 2.0, IDFT = -2.0, PI = acos(-1.0);
const int MXN = 1e5+10;
int n, m, r[MXN<<2];
struct Complex {
    double r, i;
    Complex(double _r = 0, double _i = 0) : r(_r), i(_i) {}
    Complex operator + (const Complex & x) {
        return Complex(r + x.r, i + x.i);
    }
    Complex operator += (const Complex & x) {
        r += x.r, i += x.i;
        return *this;
    }
    Complex operator - (const Complex & x) {
        return Complex(r - x.r, i - x.i);
    }
    Complex operator -= (const Complex & x) {
        r -= x.r, i -= x.i;
        return *this;
    }
    Complex operator * (const Complex & x) {
        return Complex(r * x.r - i * x.i, r * x.i + i * x.r);
    }
    Complex operator *= (const Complex & x) { // x is this
        double xr = x.r, xi = x.i, tr = r;
        r = r * xr - i * xi, i = tr * xi + i * xr;
        return *this;
    }
    void print(char pad){
        printf("%d%c", (int)(r+0.5), pad);
    }
}p1[MXN<<2], p2[MXN<<2];
void fft(Complex p[], int len, double mode){
    for(int i = 0; i < len; i++) if(i < r[i]) swap(p[i], p[r[i]]);
    for(int i = 2, mid = 1; i <= len; i <<= 1, mid <<= 1){
        Complex wn(cos(mode*PI/i), sin(mode*PI/i));
        for(int s = 0; s < len; s += i){
            Complex w(1.0, 0.0);
            for(int t = s; t < s + mid; ++t, w *= wn){
                Complex l = p[t], r = w*p[t+mid];
                p[t] = l + r, p[t+mid] = l - r;
            }
        }
    }
    if(mode == DFT) return;
    for(int i = 0; i < len; ++i) p[i].r /= len;
}
int main() {    
    int t, len, bit;
    scanf("%d", &t);
    while(t--){
        for(int i = 0; i < MXN; ++i) p1[i] = p2[i] = {0, 0};
        scanf("%d%d", &n, &m);
        for(int i = 0; i <= n; ++i) scanf("%lf", &p1[i].r), p1[i].i = 0;
        for(int i = 0; i <= m; ++i) scanf("%lf", &p2[i].r), p2[i].i = 0;
        bit = 1, len = n+m;
        while(len >>= 1) ++bit;
        len = 1 << bit;
        for(int i = 0; i < len; ++i) r[i]=(r[i>>1]>>1)|((i&1)<<(bit-1));
        fft(p1, len, DFT), fft(p2, len, DFT);
        for(int i = 0; i < len; ++i) p1[i] *= p2[i];
        fft(p1, len, IDFT);
        len = n + m;
        for(int i = 0; i < len; ++i) p1[i].print(' ');
        p1[len].print('\\n');
    }
    return 0;
}

以上是关于多项式乘积(fft)的主要内容,如果未能解决你的问题,请参考以下文章

FFT

FFT习题

多项式的基本运算(FFT和NTT)总结

hdu 5885 XM Reserves(FFT)

FFT详解

FFT(板子)