BZOJ 3527 [Zjoi2014]力 ——FFT

【题目分析】

    FFT,构造数列进行卷积,挺裸的一道题目诶。

    还是写起来并不顺手,再练。

【代码】

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)

#define maxn 500005

const double pi=acos(-1.0);
const double mypi=3.1415926589793238462643383279502;

struct Complex{
	double x,y;
	Complex operator + (Complex & a) const {Complex b; return b.x=x+a.x,b.y=y+a.y,b;}
	Complex operator - (Complex & a) const {Complex b; return b.x=x-a.x,b.y=y-a.y,b;}
	Complex operator * (Complex & a) const {Complex b; return b.x=x*a.x-y*a.y,b.y=x*a.y+y*a.x,b;}
}a[maxn],b[maxn],c[maxn];

int n,len,m,rev[maxn],top;

void FFT(Complex * x,int n,int flag)
{
	F(i,0,n-1) if (rev[i]>i) swap(x[rev[i]],x[i]);
	for (int m=2;m<=n;m<<=1)
	{
		Complex wn; wn.x=cos(2.0*pi/m*flag); wn.y=sin(2.0*pi/m*flag);
		int mid=m>>1;
		for (int i=0;i<n;i+=m)
		{
			Complex w; w.x=1.0; w.y=0;
			for (int j=0;j<mid;++j)
			{
				Complex u=x[i+j],v=x[i+j+mid]*w;
				x[i+j]=u+v; x[i+j+mid]=u-v;
				w=w*wn;
			}
		}
	}
}

int main()
{
	scanf("%d",&n); top=n;
	F(i,0,n-1) scanf("%lf",&a[i].x);
	F(i,0,2*n-2)
	{
		if (i==n-1) continue;
		b[i].x=1.0/(n-1-i)/(n-1-i);
//		printf("%d %d %.6f\n",i,(n-1-i),1.0/(n-1-i)/(n-1-i));
		if (i<n-1) b[i].x*=-1;
	}
//	F(i,0,2*n-2) printf("%f\n",b[i].x);
	m=1; n=2*n-1;
	while (m<=n) m<<=1,len++; n=m;
	F(i,0,n-1)
	{
		int t=i,ret=0;
		F(j,1,len) ret<<=1,ret|=t&1,t>>=1;
		rev[i]=ret;
	}
	FFT(a,n,1); FFT(b,n,1);
	F(i,0,n) c[i]=a[i]*b[i];
	FFT(c,n,-1);
	F(i,top-1,2*top-2) printf("%.3f\n",c[i].x/n);
}

  

posted @ 2017-02-10 22:43  SfailSth  阅读(266)  评论(0编辑  收藏  举报