P3803 多项式乘积(FFT)

Posted jpphy0

tags:

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

目录

问题

P3803 多项式乘积 - https://www.luogu.com.cn/problem/P3803

分析

  • fft

代码

#include <bits/stdc++.h>
using namespace std;
const double DFT = 2.0, IDFT = -2.0, PI = acos(-1.0);
const int MXN = 1e6+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 len, bit;    
    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;

#include <bits/stdc++.h>
using namespace std;
typedef complex<double> cd;
const double DFT = 2.0, IDFT = -2.0, PI = acos(-1.0);
const int MXN = 1e6+10;
int n, m, r[MXN<<2];
cd p1[MXN<<2], p2[MXN<<2];
void fft(cd 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)
        cd wn(cos(mode*PI/i), sin(mode*PI/i));
        for(int s = 0; s < len; s += i)
            cd w(1.0, 0.0);
            for(int t = s; t < s + mid; ++t, w *= wn)
                cd 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] /= len;

int main()     
    int len, bit;
    scanf("%d%d", &n, &m);
    for(int i = 0; i < MXN; ++i) p1[i] = p2[i] = 0;        
    for(int x, i = 0; i <= n; ++i) scanf("%d", &x), p1[i] = x;
    for(int x, i = 0; i <= m; ++i) scanf("%d", &x), p2[i] = x;
    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)  printf("%d ", (int)(p1[i].real()+0.5));
    printf("%d", (int)(p1[len].real()+0.5));
    return 0;

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

FFT

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

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

[uoj#34] [洛谷P3803] 多项式乘法(FFT)

luogu P3803 模板多项式乘法(FFT)

FFT习题