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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jpphy0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值