题目大意
给定 n n n 个数 q i q_i qi,定义 F j = ∑ i < j q i q j ( i − j ) 2 − ∑ i > j q i q j ( i − j ) 2 F_j=\sum_{i<j}\dfrac{q_iq_j}{(i-j)^2}-\sum_{i>j}\dfrac{q_iq_j}{(i-j)^2} Fj=i<j∑(i−j)2qiqj−i>j∑(i−j)2qiqj令 E i = F i q i E_i=\dfrac{F_i}{q_i} Ei=qiFi,求 E i E_i Ei。
题解
首先需要牢记卷积的形式:
c
k
=
∑
i
=
1
k
a
i
b
k
−
i
c_k=\sum\limits_{i=1}^ka_ib_{k-i}
ck=i=1∑kaibk−i,即满足两个数组的下标和为
sigma
\text{sigma}
sigma 的上标。
将
F
i
F_i
Fi 展开得
E
j
=
∑
i
<
j
q
i
(
i
−
j
)
2
−
∑
i
>
j
q
i
(
i
−
j
)
2
E_j=\sum_{i<j}\dfrac{q_i}{(i-j)^2}-\sum_{i>j}\dfrac{q_i}{(i-j)^2}
Ej=i<j∑(i−j)2qi−i>j∑(i−j)2qi
更改枚举顺序
E
j
=
∑
i
=
1
j
−
1
q
i
(
i
−
j
)
2
−
∑
i
=
j
+
1
n
q
i
(
i
−
j
)
2
E_j=\sum_{i=1}^{j-1}\dfrac{q_i}{(i-j)^2}-\sum_{i=j+1}^{n}\dfrac{q_i}{(i-j)^2}
Ej=i=1∑j−1(i−j)2qi−i=j+1∑n(i−j)2qi
令
f
i
=
q
i
f_i=q_i
fi=qi,
g
i
=
1
i
2
g_i=\dfrac{1}{i^2}
gi=i21,特别地,
g
0
=
0
g_0=0
g0=0,则有:
E
j
=
∑
i
=
1
j
−
1
f
i
g
i
−
j
−
∑
i
=
j
+
1
n
f
i
g
i
−
j
E_j=\sum_{i=1}^{j-1}f_ig_{i-j}-\sum_{i=j+1}^{n}f_ig_{i-j}
Ej=i=1∑j−1figi−j−i=j+1∑nfigi−j
又
g
i
−
j
=
g
j
−
i
g_{i-j}=g_{j-i}
gi−j=gj−i ,则有:
A
j
=
∑
i
=
1
j
−
1
f
i
g
i
−
j
=
∑
i
=
1
j
−
1
f
i
g
j
−
i
=
∑
i
=
1
j
f
i
g
j
−
i
A_j=\sum_{i=1}^{j-1}f_ig_{i-j}=\sum_{i=1}^{j-1}f_ig_{j- i}=\sum_{i=1}^{j}f_ig_{j-i}
Aj=i=1∑j−1figi−j=i=1∑j−1figj−i=i=1∑jfigj−i
就是一个标准的卷积。然后考虑 B j = ∑ i = j + 1 n f i g i − j = ∑ i = 1 n − j f i + j g i B_j=\sum\limits_{i=j+1}^{n}f_ig_{i-j}=\sum\limits_{i=1}^{n-j}f_{i+j}g_{i} Bj=i=j+1∑nfigi−j=i=1∑n−jfi+jgi
令
p
i
=
f
n
−
i
p_i=f_{n-i}
pi=fn−i,则
p
n
−
i
−
j
=
f
i
+
j
p_{n-i-j}=f_{i+j}
pn−i−j=fi+j,则有:
B
j
=
∑
i
=
1
n
−
j
f
i
+
j
g
i
=
∑
i
=
1
n
−
j
p
n
−
i
−
j
g
i
=
B
n
−
j
′
B_j=\sum\limits_{i=1}^{n-j}f_{i+j}g_{i}=\sum_{i=1}^{n-j} p_{n-i-j}g_i=B'_{n-j}
Bj=i=1∑n−jfi+jgi=i=1∑n−jpn−i−jgi=Bn−j′
则可以用FFT求出 B ′ B' B′,然后根据 B i = B n − i ′ B_i=B'_{n-i} Bi=Bn−i′ 计算。
代码
注意精度问题(别问我怎么知道的):
- 不要写 1.0 / ( i ∗ i ) 1.0/(i*i) 1.0/(i∗i),写 1.0 / i / i 1.0/i/i 1.0/i/i
- 不要
ans[i]/=limit
,直接输出就好。
#include<bits/stdc++.h>
using namespace std;
const int maxn=862154;
const double pi=acos((double)-1.0);
struct comp{
double x,y;
comp(double xx=0,double yy=0):x(xx),y(yy) {}
friend comp operator+(const comp &x,const comp &y) {return comp(x.x+y.x,x.y+y.y);}
friend comp operator-(const comp &x,const comp &y) {return comp(x.x-y.x,x.y-y.y);}
friend comp operator*(const comp &a,const comp &b) {return comp(a.x*b.x-a.y*b.y,a.x*b.y+b.x*a.y);}
}f[maxn],g[maxn],p[maxn],A[maxn],B[maxn];
int limit=1,n,l=0,r[maxn];
void fft(comp *t,int ty){
for(int i=0;i<limit;i++)
if(i<r[i])
swap(t[i],t[r[i]]);
for(int mid=1;mid<limit;mid<<=1){
comp wn(cos(pi/mid),ty*sin(pi/mid));
for(int j=0,R=(mid<<1);j<limit;j+=R){
comp w(1,0);
for(int k=0;k<mid;k++,w=w*wn){
comp x=t[j+k],y=w*t[j+k+mid];
t[j+k]=x+y;
t[j+k+mid]=x-y;
}
}
}
}
void reset(int n,int m){
while(limit<=n+m+2)
limit<<=1,++l;
for(int i=1;i<limit;i++)
r[i]=((r[i>>1]>>1)|((i&1)<<(l-1)));
}
int main(void)
{
memset(f,0,sizeof f);
memset(g,0,sizeof g);
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lf",&f[i].x);
g[i].x=(double)1.0/i/i;
p[n-i].x=f[i].x;
}
reset(n,n);
fft(f,1);fft(g,1);fft(p,1);
for(int i=0;i<limit;i++)
A[i]=g[i]*f[i];
fft(A,-1);
for(int i=0;i<limit;i++)
B[i]=g[i]*p[i];
fft(B,-1);
for(int i=1;i<=n;i++)
printf("%.6lf\n",A[i].x/limit-B[n-i].x/limit);
return 0;
}