P3338 [ZJOI2014]力

传送门

看来对 FFT 的理解仍只是在表层模板而已,对问题还是不会转化


思路

我们先回顾卷积的形式:

\[W_k=\sum_{i=0}^kF_i\times G_{k-i} \]

这些表示的都是系数

回到这道题,题目其实让我们求得应该是 \(E_i=\sum_{j=1}^{i-1}\frac{q[j]}{(i-j)^2}-\sum_{j=i+1}^{n}\frac{q[j]}{(j-i)^2}\)

因为这是板子题, 我们应该要将式子转化成卷积的形式

我们令 \(F[k]=q[k], G[k]=\frac{1}{k^2}\),因此有

\[E_i=\sum_{j=1}^{i-1}F[j]G[i-j]-\sum_{j=i+1}^{n}F[j]G[j-i] \]

我们考虑让 \(F[0]=G[0]=0\),让形式更靠近卷积的形式:

\[E_i=\sum_{j=0}^{i}F[j]G[i-j]-\sum_{j=i}^{n}F[j]G[j-i] \]

右式的左半部分成功化成卷积形式了,但右边还是差点

我们考虑令 \(j=0\)

\[E_i=\sum_{j=0}^{i}F[j]G[i-j]-\sum_{j=0}^{n-i}F[j+i]G[j] \]

我们再考虑令 \(F'[k]=F[n-k]\)

\[E_i=\sum_{j=0}^{i}F[j]G[i-j]-\sum_{j=0}^{n-i}F'[n-i-j]G[j] \]

这时我们就成功转化了,为了让式子更好看,我们令 \(r=n-i\)

\[E_i=\sum_{j=0}^{i}F[j]G[i-j]-\sum_{j=0}^{r}F'[r-j]G[j] \]

开卷!

令函数 \(A(x),B(x),C(x)\) 的系数表示分别为 \(\{F[k]|0\le k\le n\},\{F'[k]|0\le k\le n\},\{G[k]|0\le k\le n\}\)

求出 \(X(x)=A(x)*C(x)\), \(Y(x)=B(x)*C(x)\)

最后的答案就为 \(E_i=X_i-Y_{n-i}\)


代码

#include<iostream>
#include<fstream>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#define LL long long
const int N = 2097160;
const double Pi = acos(-1);
struct Complex
{
    double a, b;
    Complex(double na = 0, double nb = 0) : a(na), b(nb) {}
    Complex operator + (const Complex &x) const {return (Complex){a + x.a, b + x.b};}
    Complex operator - (const Complex &x) const {return (Complex){a - x.a, b - x.b};}
    Complex operator * (const Complex &x) const {return (Complex){a * x.a - b * x.b, a * x.b + b * x.a};}
}A[N], B[N], C[N];
int n, m, t[N];
inline void FFT(Complex *f, bool I)
{
    for(int i = 1; i < n; i++)
        if(i < t[i]) std::swap(f[i], f[t[i]]);
    for(int now = 2, la = 1; now <= n; now <<= 1, la <<= 1)
    {
        Complex ADF(cos(2.0 * Pi / now), sin(2.0 * Pi / now));
        if(I) ADF.b = -ADF.b;
        for(int l = 0; l < n; l += now)
        {
            Complex buf(1, 0);
            for(int k = l; k < l + la; k++)
            {
                Complex mul = buf * f[k + la];
                f[k + la] = f[k] - mul;
                f[k] = f[k] + mul;
                buf = buf * ADF;
            }
        }
    }
}
signed main()
{
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
        scanf("%lf", &A[i].a), B[n - i].a = A[i].a, C[i].a = (1.0 / i / i);
    for(m = n << 1, n = 1; n <= m; n <<= 1);
    for(int i = 1; i < n; i++)
        t[i] = (t[i >> 1] >> 1) | (i & 1 ? n >> 1 : 0);
    FFT(A, 0); FFT(B, 0); FFT(C, 0);
    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);
    m >>= 1;
    for(int i = 1; i <= m; i++)
        printf("%lf\n", A[i].a / n - B[m - i].a / n);
    return 0;
}
posted @ 2022-04-06 14:35  zuytong  阅读(20)  评论(0编辑  收藏  举报