uoj34多项式乘法

来源:互联网 发布:电子病历软件 免费 编辑:程序博客网 时间:2024/06/05 08:45

这是一道模板题。
给你两个多项式,请输出乘起来后的多项式。

输入格式
第一行两个整数 nn 和 mm,分别表示两个多项式的次数。
第二行 n+1n+1 个整数,分别表示第一个多项式的 00 到 nn 次项前的系数。
第三行 m+1m+1 个整数,分别表示第一个多项式的 00 到 mm 次项前的系数。

输出格式
一行 n+m+1n+m+1 个整数,分别表示乘起来后的多项式的 00 到 n+mn+m 次项前的系数。

样例一
input
1 2
1 2
1 2 1

output
1 4 5 2

explanation
(1+2x)⋅(1+2x+x2)=1+4x+5x2+2x3(1+2x)⋅(1+2x+x2)=1+4x+5x2+2x3

限制与约定
0≤n,m≤1050≤n,m≤105,保证输入中的系数大于等于 00 且小于等于 99。

时间限制:1s
空间限制:256MB

分析:
如题所言,确实是一道FFT模板题,
寻求曲神帮助
虽然曲神神的有点不可思议,但人还是很亲切的
第一次写,代码极为丑陋
这里写图片描述

这里写代码片#include<cstdio>#include<cstring>#include<iostream>#include<cmath>using namespace std;const int N=301000;  //数组大小避免开成2的次方 const double pi=acos(-1.0);struct node{    double a,b;    node (double aa=0,double bb=0)    {        a=aa;b=bb;    }};node a[N],b[N],omega[N],a_omega[N]; int n,m,k,l;node operator +(const node &x,const node &y){return node(x.a+y.a,x.b+y.b);}node operator -(const node &x,const node &y){return node(x.a-y.a,x.b-y.b);}node operator *(const node &x,const node &y){return node(x.a*y.a-x.b*y.b,x.a*y.b+x.b*y.a);}node operator *(const node &x,const double &y){return node(x.a*y,x.b*y);}void init(int n){    for (int i=0;i<n;i++)    {        omega[i]=node(cos(2.0*pi*i/n),sin(2.0*pi*i/n));        a_omega[i]=node(cos(2.0*pi*i/n),-sin(2.0*pi*i/n));    }}void FFT(int n,node *a,node *w){    int i,j=0,k;    for (i=0;i<n;i++)  //很显然这就是优美的rev操作     {        if (i>j) swap(a[i],a[j]);        for (int l=n>>1;(j^=l)<l;l>>=1);    }    for (int i=2;i<=n;i<<=1)  //合并     {        int m=i>>1;  //一半区间的长度         for (int j=0;j<n;j+=i)            for (k=0;k<m;k++)            {                node z=a[j+m+k]*w[n/i*k];                a[j+m+k]=a[j+k]-z;                a[j+k]=a[j+k]+z;            }     }}int main(){    int fn;    scanf("%d%d",&n,&m);    for (int i=0;i<=n;i++) scanf("%lf",&a[i].a);    for (int i=0;i<=m;i++) scanf("%lf",&b[i].a);    fn=1;    while (fn<=n+m) fn<<=1;   //找到大于n+m的最小2次幂    init(fn);     FFT(fn,a,omega);    FFT(fn,b,omega);    for (int i=0;i<=fn;i++)        a[i]=a[i]*b[i];    FFT(fn,a,a_omega);    for (int i=0;i<=n+m;i++) printf("%d ",(int)(a[i].a/fn+0.5));  //四舍五入 }