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

题面

题目背景

这是一道 FFT 模板题

题目描述

给定一个$n$次多项式$F(x)$,和一个$m$次多项式$G(x)$

请求出$F(x)$和$G(x)$的卷积。

输入格式

第一行 2 个正整数$n,m$

接下来一行$n+1$个数字,从低到高表示$F(x)$的系数。

接下来一行$m+1$个数字,从低到高表示$G(x)$的系数。

输出格式

一行$n+m+1$个数字,从低到高表示$F(x)*G(x)$的系数。

输入输出样例

输入 #1
1 2
1 2
1 2 1
输出 #1
1 4 5 2

说明/提示

保证输入中的系数大于等于 0 且小于等于 9

对于100%的数据:$n,m<=10^{6}$

 

题意

就是一道FFT模板,给出一个n次多项式系数,一个m次多项式系数,求它们乘积的多项式每一项的系数。

题解

模板,不解释

#include<cmath>
using namespace std;
const int N=1e7+5;
const double PI=acos(-1.0);
int lena,lenb,n=1,lim,r[N];
struct cp{
    double x,y;
    cp(double _x=0,double _y=0){
        x=_x;y=_y;
    }
    cp operator*(cp b){
        return cp(x*b.x-y*b.y,x*b.y+y*b.x);
    }
    cp operator+(cp b){
        return cp(x+b.x,y+b.y);
    }
    cp operator-(cp b){
        return cp(x-b.x,y-b.y);
    }
}a[N],b[N];
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
void FFT(cp *A,int tp){
    for(int i=0;i<n;i++)if(i<r[i])swap(A[i],A[r[i]]);
    for(int i=1;i<n;i<<=1){
        cp W(cos(PI/i),tp*sin(PI/i));
        for(int j=i<<1,k=0;k<n;k+=j){
            cp w(1,0);
            for(int l=0;l<i;l++,w=w*W){
                cp x=A[k+l],y=w*A[k+i+l];//替代buf
                A[k+l]=x+y;
                A[k+i+l]=x-y;
            }
        }
    }
}
int main(){
    lena=read();lenb=read();
    while(n<=lena+lenb)n<<=1,lim++;
    for(int i=0;i<=lena;i++)a[i].x=read();
    for(int i=0;i<=lenb;i++)b[i].x=read();
    for(int i=0;i<n;i++)r[i]=(r[i>>1]>>1)|((i&1)<<(lim-1));
    FFT(a,1);
    FFT(b,1);
    for(int i=0;i<=n;i++)a[i]=a[i]*b[i];
    FFT(a,-1);
    for(int i=0;i<=lena+lenb;i++)printf("%d ",(int)(a[i].x/n+0.5));
}

  

posted @ 2019-08-24 22:17  Evan704  阅读(243)  评论(0编辑  收藏  举报