P3338 [ZJOI2014]力 /// FFT 公式转化翻转

题目大意:

https://www.luogu.org/problemnew/show/P3338

题解

#include <bits/stdc++.h>
#define N 300005
#define PI acos(-1.0)
using namespace std;

struct cpx {
    double x,y;
    cpx (double a=0.0,double b=0.0) { x=a; y=b; }
    cpx operator - (const cpx &b)const { return cpx(x-b.x, y-b.y); }
    cpx operator + (const cpx &b)const { return cpx(x+b.x, y+b.y); }
    cpx operator * (const cpx &b)const { return cpx(x*b.x-y*b.y, x*b.y+y*b.x); }
}f1[N], f2[N], g[N];
int n, l, len, r[N];

void fft(cpx a[],double on)
{
    for(int i=0;i<len;i++)
        if(i<r[i]) swap(a[i],a[r[i]]);
    for(int i=1;i<len;i<<=1) {
        cpx wn(cos(PI/i),on*sin(PI/i));
        for(int j=0;j<len;j+=(i<<1)) {
            cpx w(1,0);
            for(int k=0;k<i;k++,w=w*wn) {
                cpx u=a[j+k], v=w*a[j+k+i];
                a[j+k]=u+v, a[j+k+i]=u-v;
            }
        }
    }
}

void solve()
{
    fft(f1,1); fft(f2,1); fft(g,1);
    for(int i=0;i<=len;i++)
        f1[i]=f1[i]*g[i], f2[i]=f2[i]*g[i];
    fft(f1,-1); fft(f2,-1);
    for(int i=0;i<=len;i++)
        f1[i].x=f1[i].x/len, f2[i].x=f2[i].x/len;
    for(int i=1;i<=n;i++)
        printf("%.3f\n",-f2[n+1-i].x+f1[i].x);
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) {
        scanf("%lf",&f1[i].x);
        f2[n+1-i].x=f1[i].x;
        g[i].x=(double)(1.0/i/i);
    }

    len=1; l=0;
    while(len<(n<<1)) len<<=1, l++;
    for(int i=0;i<=len;i++)
        r[i]=( r[i>>1]>>1 )|( (i&1)<<(l-1) );

    solve();

    return 0;
}
View Code

 

posted @ 2018-08-13 15:16  _Jessie  阅读(294)  评论(0编辑  收藏  举报