洛谷 P3723 [AH2017/HNOI2017]礼物

发布时间 2023-06-01 13:47:50作者: Chy12321

由题面可得:

\[E_j = \sum_{i = 1}^{j - 1} \frac{q_i}{(i - j)^2} - \sum_{i = j + 1}^{n} \frac{q_i}{(i - j)^2} \]

\(q_0 = 0\),并将没有意义的分式的值视为 \(0\),则有:

\[E_j = \sum_{i = 0}^j \frac{q_i}{(i - j)^2} - \sum_{i = j}^n \frac{q_i}{(i - j)^2} \]

\(A(i) = q_i, B(i) = \dfrac 1{i^2}\),则原式可化为:

\[E_j = \sum_{i = 0}^j[A(i) \times B(j - i)] - \sum_{i = 0}^{n - j}[A(i + j) \times B(i)] \]

\(A'(i) = A(n - i)\),则有:

\[\begin{aligned} E_j &= \sum_{i = 0}^j[A(i) \times B(j - i)] - \sum_{i = 0}^{n - j}[A'(n - i - j) \times B(i)] \\ &= (A * B)[j] - (A' * B)[n - j] \end{aligned} \]

FFT 加速卷积即可。

代码:

#include <bits/stdc++.h>

#define MAXN 400100

using namespace std;

const double PI = acos(-1);

int n, len = 1, bits, rev[MAXN];
double q[MAXN];

struct Complex {
    double r, i;

    Complex operator+(const Complex &rhs) const {
        return {r + rhs.r, i + rhs.i};
    }

    Complex operator-(const Complex &rhs) const {
        return {r - rhs.r, i - rhs.i};
    }

    Complex operator*(const Complex &rhs) const {
        return {r * rhs.r - i * rhs.i, r * rhs.i + i * rhs.r};
    }
} a[MAXN], b[MAXN], a1[MAXN];

void FFT(Complex A[], int flag) {
    for (int i = 0; i < len; i++) if (rev[i] > i) swap(A[i], A[rev[i]]);
    for (int i = 1; i < len; i <<= 1) {
        Complex wn = {cos(PI / i), flag * sin(PI / i)};
        for (int j = 0; j < len; j += (i << 1)) {
            Complex w = {1, 0};
            for (int k = j; k < j + i; k++) {
                Complex t = w * A[i + k];
                A[k + i] = A[k] - t;
                A[k] = A[k] + t;
                w = w * wn;
            }
        }
    }
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%lf", &q[i]);
    for (int i = 1; i <= n; i++) a[i].r = a1[n - i].r = q[i];
    for (int i = 1; i <= n; i++) b[i].r = 1.0 / i / i;
    while (len < (n << 1)) len <<= 1, bits++;
    for (int i = 0; i < len; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (bits - 1));
    FFT(a, 1), FFT(a1, 1), FFT(b, 1);
    for (int i = 0; i < len; i++) a[i] = a[i] * b[i], a1[i] = a1[i] * b[i];
    FFT(a, -1), FFT(a1, -1);
    for (int i = 1; i <= n; i++) printf("%lf\n", (a[i].r - a1[n - i].r) / len);
    return 0;
}