首页 > 代码库 > BZOJ 2194 快速傅立叶之二 快速傅里叶变换

BZOJ 2194 快速傅立叶之二 快速傅里叶变换

题目大意:给定两个长度为n的序列a和b,求c[k]=Σa[i]*b[i-k]

这东西不是卷积的形式,因此我们将b数组反转,之后就是卷积的形式了

然后就愉♂悦地上FFT吧

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 263000
#define PI 3.1415926535897932384626433832795028841971
using namespace std;
struct Complex{
	double a,b;
	Complex() {}
	Complex(double _,double __):a(_),b(__) {}
	Complex operator + (const Complex &x) const
	{
		return Complex(a+x.a,b+x.b);
	}
	Complex operator - (const Complex &x) const
	{
		return Complex(a-x.a,b-x.b);
	}
	Complex operator * (const Complex &x) const
	{
		return Complex(a*x.a-b*x.b,a*x.b+b*x.a);
	}
	void operator *= (const Complex &x)
	{
		*this=(*this)*x;
	}
}a[M],b[M],p[M];
int n;
void FFT(Complex x[],int n,int type)
{
	static Complex temp[M];
	if(n==1) return ;
	int i;
	for(i=0;i<n;i+=2)
		temp[i>>1]=x[i],temp[i+n>>1]=x[i+1];
	memcpy(x,temp,sizeof(Complex)*n);
	Complex *l=x,*r=x+(n>>1);
	FFT(l,n>>1,type);FFT(r,n>>1,type);
	Complex root(cos(type*2*PI/n),sin(type*2*PI/n)),w(1,0);
	for(i=0;i<n>>1;i++,w*=root)
		temp[i]=l[i]+w*r[i],temp[i+(n>>1)]=l[i]-w*r[i];
	memcpy(x,temp,sizeof(Complex)*n);
}
int main()
{
	int i,digit;
	cin>>n;
	for(i=0;i<n;i++)
		scanf("%lf%lf",&a[i].a,&b[n-i-1].a);
	for(digit=1;digit<=n<<1;digit<<=1);
	FFT(a,digit,1);FFT(b,digit,1);
	for(i=0;i<digit;i++)
		p[i]=a[i]*b[i];
	FFT(p,digit,-1);
	for(i=n-1;i<n+n-1;i++)
		printf("%d\n",int(p[i].a/digit+0.5) );
}


BZOJ 2194 快速傅立叶之二 快速傅里叶变换