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); }