BZOJ 3527: [Zjoi2014]力 FFT

title

BZOJ 3527

LUOGU 3338

Description

Given \ (n-\) number \ (Q_I \) , gives \ (F_j \) is defined as follows:

\(F_j = \sum_{i<j}\frac{q_i q_j}{(i-j)^2 }-\sum_{i>j}\frac{q_i q_j}{(i-j)^2 }\)

\(E_i=\frac{F_i}{q_i}\),求 \(E_i\)

analysis

\[ E_j=\frac{F_j}{q_j}=\sum_{i<j}\frac{q_i}{(i-j)^2}-\sum_{i>j}\frac{q_i}{(i-j)^2} \]


\[ f[i]=q_i,g[i]=\frac{1}{i^2} \]

则原式为
\[ \sum_{i<j}f[i]g[j-i]-\sum_{i>j}f[i]g[j-i] \]


\[ \sum_{i=0}^{j-1}f[i]g[j-i]-\sum_{i=j+1}^{n}f[i]g[j-i] \]

Set \ (f '\) of \ (F \) value is reversed, the original formula
\ [\ sum_ {i = 0 } ^ {j-1} f [i] g [ji] - \ sum_ { i = 0} ^ {j- 1} f '[i] g [ji] \]

Easy to see that this is a form of convolution directly \ (FFT \) can be.

code

#include<bits/stdc++.h>

typedef long double ld;
const int maxn=5e5+10;
const ld Pi=acos(-1);

namespace IO
{
    char buf[1<<15],*fs,*ft;
    inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
    template<typename T>inline void read(T &x)
    {
        x=0;
        T f=1, ch=getchar();
        while (!isdigit(ch) && ch^'-') ch=getchar();
        if (ch=='-') f=-1, ch=getchar();
        while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
        x*=f;
    }
}

using IO::read;

struct Orz{double a,b;}A[maxn],B[maxn],C[maxn],W[maxn];
inline Orz operator + (Orz a,Orz b) { return (Orz){a.a+b.a,a.b+b.b}; }
inline Orz operator - (Orz a,Orz b) { return (Orz){a.a-b.a,a.b-b.b}; }
inline Orz operator * (Orz a,Orz b) { return (Orz){a.a*b.a-a.b*b.b,a.a*b.b+a.b*b.a}; }

int N,r[maxn],l;
inline void FFT(Orz *P,int opt)
{
    for (int i=1; i<N; ++i) if (i<r[i]) std::swap(P[i],P[r[i]]);
    for (int i=1; i<N; i<<=1)
        for (int p=i<<1,j=0; j<N; j+=p)
            for (int k=0; k<i; ++k)
            {
                Orz w=(Orz){W[N/i*k].a,W[N/i*k].b*opt};
                Orz x=P[j+k], y=w*P[j+k+i];
                P[j+k]=x+y, P[j+k+i]=x-y;
            }
    if (opt==-1)
        for (int i=0; i<N; ++i) P[i].a/=N;
}

int main()
{
    int n;read(n);
    for (N=1; N<=(n<<1); N<<=1) ++l;
    for (int i=0; i<N; ++i) r[i]=( (r[i>>1]>>1) | ((i&1)<<(l-1)) );
    for (int i=1; i<N; i<<=1)
        for (int k=0; k<i; ++k) W[N/i*k]=(Orz){cos(k*Pi/i),sin(k*Pi/i)};
    for (int i=1; i<=n; ++i) scanf("%lf",&A[i].a), B[n+1-i].a=A[i].a;
    for (int i=1; i<=n; ++i) C[i].a=(1.0/(ld)i)/(ld)i;

    FFT(A,1),FFT(B,1),FFT(C,1);
    for (int i=0; i<N; ++i) A[i]=A[i]*C[i], B[i]=B[i]*C[i];
    FFT(A,-1),FFT(B,-1);
    for (int i=1; i<=n; ++i) printf("%.3lf\n",A[i].a-B[n+1-i].a);
    return 0;
}

Guess you like

Origin www.cnblogs.com/G-hsm/p/11412361.html