【UOJ 34】 多项式乘法 (FFT)

【题意】 给你两个多项式,请输出乘起来后的多项式。

 

 

 

先打一个递归版本的模板。。。 

 

 

#include<cstdio>
#include<iostream>
#include<cmath>
#include<memory.h>
#define N 400010
using namespace std;
const double pi=acos(-1);

struct P
{
    double x,y;
	P() {x=y=0;}
    P(double x,double y):x(x),y(y){}
}a[N],b[N];

P operator + (P x,P y) {return P(x.x+y.x,x.y+y.y);}
P operator - (P x,P y) {return P(x.x-y.x,x.y-y.y);}
P operator * (P x,P y) {return P(x.x*y.x-x.y*y.y,x.x*y.y+x.y*y.x);}

void fft(P *s,int n,int t)
{
	if(n==1) return;
	P a0[n>>1],a1[n>>1];
	for(int i=0;i<=n;i+=2) a0[i>>1]=s[i],a1[i>>1]=s[i+1];
	fft(a0,n>>1,t);fft(a1,n>>1,t);
	P wn(cos(2*pi/n),t*sin(2*pi/n)),w(1,0);
	for(int i=0;i<(n>>1);i++,w=w*wn) s[i]=a0[i]+w*a1[i],s[i+(n>>1)]=a0[i]-w*a1[i];
	//w^2=(w+(n>>1))^2 均匀分布在圆上面?
	//w[i^2,n]=w[i/2,n/2] 折半引理
	//s[i]=a0’(i^2)+i*a1’(i^2)=a0(i)+i*a1(i)
	//s[i+n>>1]=a0’((i+n>>1)^2)+i*a1’((i+n>>1)^2)=a0’(i^2)-i*a1’(i^2)
	//因为i=-(i+n>>1) 折半引理
}

int main()
{
	int n,m,nn;
    scanf("%d%d",&n,&m);
    memset(a,0,sizeof(a));memset(b,0,sizeof(b));
    for(int i=0;i<=n;i++) scanf("%lf",&a[i].x);
    for(int i=0;i<=m;i++) scanf("%lf",&b[i].x);
    nn=1;while (nn<=n+m) nn<<=1;
    fft(a,nn,1);fft(b,nn,1);
    for(int i=0;i<=nn;i++) a[i]=a[i]*b[i];
    fft(a,nn,-1);
    for(int i=0;i<=n+m;i++) printf("%d ",(int)(a[i].x/nn+0.5));
	return 0;
}

  

2017-03-04 08:51:27

 

posted @ 2017-03-04 08:44  konjak魔芋  阅读(747)  评论(0编辑  收藏  举报