BZOJ3527: [Zjoi2014]力 [FFT]

化简之后,发现减号左边的式子是一个卷积。右边的式子,把一个函数倒序就是卷积,分别FFT,求解答案。

大佬blog: https://blog.csdn.net/kyleyoung_ymj/article/details/51721495

#include <bits/stdc++.h>
#define pi acos(-1.0)
const int maxn = 300000+5;
using namespace std;
struct E{
    double real,imag;
    E(double real=0,double imag=0):real(real),imag(imag){}
    friend E operator +(E A,E B){
        return E(A.real+B.real,A.imag+B.imag);
    }
    friend E operator -(E A,E B){
        return E(A.real-B.real,A.imag-B.imag);
    }
    friend E operator *(E A,E B){
        return E(A.real*B.real-A.imag*B.imag,A.imag*B.real+A.real*B.imag);
    }
};
int n,m,L,rev[maxn];
E f[maxn],rf[maxn],g[maxn],e1[maxn],e2[maxn];
void fft(E *a,int ty){
    for(int i=0;i<n;++i)if(i<rev[i])swap(a[i],a[rev[i]]);
    for(int i=1;i<n;i<<=1){
        E wn=E(cos(pi/i),ty*sin(pi/i));
        for(int p=(i<<1),j=0;j<n;j+=p){
            E w(1,0);
            for(int k=0;k<i;++k,w=w*wn){
                E x=a[j+k],y=w*a[j+k+i];
                a[j+k]=x+y;a[j+k+i]=x-y;
            }
        }
    }
    if(ty==-1)for(int i=0;i<n;++i)a[i].real/=n;
}
int main(){
    scanf("%d",&n);--n;
    for(int i=0;i<=n;++i){double x;
        scanf("%lf",&x);
        f[i] = x;
        rf[n-i] = x;
    }
    for(int i=1;i<=n;++i)g[i]=1.0/i/i;//g[0]=0
    m=n*2;for(n=1;n<=m;n<<=1)L++;
    for(int i=0;i<n;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
    fft(f,1);fft(rf,1);fft(g,1);
    for(int i=0;i<n;++i)e1[i]=f[i]*g[i];
    for(int i=0;i<n;++i)e2[i]=rf[i]*g[i];
    fft(e1,-1);fft(e2,-1);
    for(int i=0;i<=m/2;++i)
        printf("%.3f
",e1[i].real-e2[m/2-i].real);
}

  

看起来是个简单题,可是第二部分的卷积形式,推了半天都不对。。。结果直接。学的网上写法。。。然而这题想到fft,就真的简单。