(color{#0066ff}{ 题目描述 })
给出n个数qi,给出Fj的定义如下:
(F_j = sum_{i<j}frac{q_i q_j}{(i-j)^2 }-sum_{i>j}frac{q_i q_j}{(i-j)^2 })
令Ei=Fi/qi,求Ei.
(color{#0066ff}{输入格式})
第一行一个整数n。
接下来n行每行输入一个数,第i行表示qi。
接下来为边
(color{#0066ff}{输出格式})
n行,第i行输出Ei。
与标准答案误差不超过1e-2即可。
(color{#0066ff}{输入样例})
5
4006373.885184
15375036.435759
1717456.469144
8514941.004912
1410681.345880
(color{#0066ff}{输出样例})
-16838672.693
3439.793
7509018.566
4595686.886
10903040.872
(color{#0066ff}{数据范围与提示})
对于30%的数据,n≤1000。
对于50%的数据,n≤60000。
对于100%的数据,n≤100000,0<qi<1000000000。
(color{#0066ff}{ 题解 })
把(q_i)除掉
令(f_i=p_i, g_i=frac{1}{i^2})
则(egin{aligned}F_i=sum_{j = 1}^{i - 1}f(j)*g(i-j)-sum_{j = i +1}^{n}f(j)*g(j-i)end{aligned})
考虑一个卷积(egin{aligned}f_n=sum_{i = 1}^n g(i)*h(n - i) end{aligned})
一个函数(f(i)),当做多项式,就是(x^i)的系数
不难发现,因为(i + n - i) = n
所以上面的卷积其实就是g和h卷起来第n项的系数!
回到本题
将前面的(sum)用FFT算出来,因为(j+i-j=i),因此前面的部分第i项的系数就是第i个ans
后面的(sum)不好弄,要把j消掉,可以将后面翻转成(egin{aligned}sum_{j = i + 1}^{n}f(j)*g(n - (j - i)+1)end{aligned})
(j + n -j+i+1=n+i+1),所以后半部分的第i个ans就是卷积的第n+i+1项(把g翻转后再卷积)
#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const double pi = acos(-1);
const int maxn = 3e5 + 10;
double p[maxn];
struct node {
double x, y;
node(double x = 0, double y = 0): x(x), y(y) {}
friend node operator + (const node &a, const node &b) { return node(a.x + b.x, a.y + b.y); }
friend node operator - (const node &a, const node &b) { return node(a.x - b.x, a.y - b.y); }
friend node operator * (const node &a, const node &b) { return node(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); }
friend node operator / (const node &a, const double &b) { return node(a.x / b, a.y / b); }
}A[maxn], B[maxn], E[maxn], F[maxn];
int len, n, r[maxn];
void FFT(node *D, int flag) {
for(int i = 0; i < len; i++) if(i < r[i]) std::swap(D[i], D[r[i]]);
for(int l = 1; l < len; l <<= 1) {
node w0(cos(pi / l), flag * sin(pi / l));
for(int i = 0; i < len; i += (l << 1)) {
node w(1, 0), *a0 = D + i, *a1 = D + i + l;
for(int k = 0; k < l; k++, a0++, a1++, w = w * w0) {
node tmp = *a1 * w;
*a1 = *a0 - tmp;
*a0 = *a0 + tmp;
}
}
}
if(flag == -1) for(int i = 0; i < len; i++) D[i] = D[i] / len;
}
int main() {
n = in();
for(int i = 1; i <= n; i++) scanf("%lf", &p[i]);
for(int i = 1; i <= n; i++) A[i].x = p[i];
for(int i = 1; i <= n; i++) B[i].x = 1.0 / i / i;
for(len = 1; len <= n + n + 2; len <<= 1);
for(int i = 0; i < len; i++) r[i] = (r[i >> 1] >> 1) | ((i & 1) * (len >> 1));
FFT(A, 1), FFT(B, 1);
for(int i = 0; i < len; i++) E[i] = A[i] * B[i];
FFT(E, -1);
for(int i = 0; i < len; i++) A[i] = B[i] = node();
for(int i = 1; i <= n; i++) A[i].x = p[i];
for(int i = 1; i <= n; i++) B[i].x = 1.0 / (n - i + 1) / (n - i + 1);
FFT(A, 1), FFT(B, 1);
for(int i = 0; i < len; i++) F[i] = A[i] * B[i];
FFT(F, -1);
for(int i = 1; i <= n; i++) printf("%.3f
", E[i].x - F[n + i + 1].x);
return 0;
}