UOJ 34 多项式乘法(FFT)

来源:互联网 发布:手机淘宝链接怎么弄 编辑:程序博客网 时间:2024/06/07 12:04

Description
给你两个多项式,请输出乘起来后的多项式
Input
第一行两个整数nm,分别表示两个多项式的次数
第二行n+1个整数,分别表示第一个多项式的0n次项前的系数
第三行m+1个整数,分别表示第一个多项式的0m次项前的系数
Output
一行n+m+1个整数,分别表示乘起来后的多项式的0n+m次项前的系数
Sample Input
1 2
1 2
1 2 1
Sample Output
1 4 5 2
Solution

FFT模版题

Code

#include<cstdio>#include<cmath>#include<algorithm>using namespace std;namespace fastIO {    #define BUF_SIZE 100000    //fread -> read    bool IOerror=0;    inline char nc()     {        static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;        if(p1==pend)         {            p1=buf;            pend=buf+fread(buf,1,BUF_SIZE,stdin);            if(pend==p1)             {                IOerror=1;                return -1;            }        }        return *p1++;    }    inline bool blank(char ch)     {        return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';    }    inline void read(int &x)     {        char ch;        while(blank(ch=nc()));        if(IOerror)return;        for(x=ch-'0';(ch=nc())>='0'&&ch<='9';x=x*10+ch-'0');    }    inline void readc(char &x)    {        char ch;        while(blank(ch=nc()));        if(IOerror)return;        x=ch;    }    #undef BUF_SIZE};using namespace fastIO;#define maxn 131072+5const double pi=acos(-1.0);struct cp {    double a,b;    cp operator +(const cp &o)const {return (cp){a+o.a,b+o.b};}    cp operator -(const cp &o)const {return (cp){a-o.a,b-o.b};}    cp operator *(const cp &o)const {return (cp){a*o.a-b*o.b,b*o.a+a*o.b};}    cp operator *(const double &o)const {return (cp){a*o,b*o};}    cp operator !() const{return (cp){a,-b};}}w[maxn];int pos[maxn];void fft_init(int len){    int j=0;    while((1<<j)<len)j++;    j--;    for(int i=0;i<len;i++)        pos[i]=pos[i>>1]>>1|((i&1)<<j);}void fft(cp *x,int len,int sta){    for(int i=0;i<len;i++)        if(i<pos[i])swap(x[i],x[pos[i]]);    w[0]=(cp){1,0};    for(unsigned i=2;i<=len;i<<=1)    {        cp g=(cp){cos(2*pi/i),sin(2*pi/i)*sta};        for(int j=i>>1;j>=0;j-=2)w[j]=w[j>>1];        for(int j=1;j<i>>1;j+=2)w[j]=w[j-1]*g;        for(int j=0;j<len;j+=i)        {            cp *a=x+j,*b=a+(i>>1);            for(int l=0;l<i>>1;l++)            {                cp o=b[l]*w[l];                b[l]=a[l]-o;                a[l]=a[l]+o;            }        }    }    if(sta==-1)for(int i=0;i<len;i++)x[i].a/=len,x[i].b/=len;}cp x[maxn],y[maxn],z[maxn];void FFT(int *a,int *b,int n,int m,int *c){    if(n<=100&&m<=100||min(n,m)<=5)    {        for(int i=0;i<n+m;i++)c[i]=0;        for(int i=0;i<n;i++)            for(int j=0;j<m;j++)                c[i+j]+=a[i]*b[j];        return ;    }    for(int i=0;i<n;i++)(i&1?x[i>>1].b:x[i>>1].a)=a[i];    for(int i=0;i<m;i++)(i&1?y[i>>1].b:y[i>>1].a)=b[i];    int len=1;    while(len<(n+m)>>1)len<<=1;    fft_init(len);    fft(x,len,1),fft(y,len,1);    for(int i=0;i<len/2;i++)    {        int j=len-1&len-i;        z[i]=x[i]*y[i]-(x[i]-!x[j])*(y[i]-!y[j])*(w[i]+(cp){1,0})*0.25;    }    for(int i=len/2;i<len;i++)    {        int j=len-1&len-i;        z[i]=x[i]*y[i]-(x[i]-!x[j])*(y[i]-!y[j])*((cp){1,0}-w[i^len>>1])*0.25;    }    fft(z,len,-1);    for(int i=0;i<n+m;i++)        if(i&1)c[i]=(int)(z[i>>1].b+0.5);        else c[i]=(int)(z[i>>1].a+0.5);}int n,m,a[maxn],b[maxn],c[maxn<<1];int main(){    read(n),read(m);    //scanf("%d%d",&n,&m);    for(int i=0;i<=n;i++)read(a[i]);//scanf("%d",&a[i]);    for(int i=0;i<=m;i++)read(b[i]);//scanf("%d",&b[i]);    FFT(a,b,n+1,m+1,c);    for(int i=0;i<=n+m;i++)printf("%d%c",c[i],i==n+m?'\n':' ');    return 0;}
原创粉丝点击