【题目分析】
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);
}