【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
浙公网安备 33010602011771号