题目:
B
Z
O
J
3527
BZOJ3527
BZOJ3527
给定数组
q
q
q,长度为
n
n
n,数组
F
F
F按以下公式求出
F
i
=
∑
j
<
i
q
i
q
j
(
i
−
j
)
2
−
∑
j
>
i
q
i
q
j
(
i
−
j
)
2
F_i=\sum_{j<i}\frac{q_iq_j}{(i-j)^2}-\sum_{j>i}\frac{q_iq_j}{(i-j)^2}
Fi=j<i∑(i−j)2qiqj−j>i∑(i−j)2qiqj
请你求出数组
E
E
E,
E
i
=
F
i
q
i
E_i=\frac{F_i}{q_i}
Ei=qiFi,
n
≤
1
0
5
n\le 10^5
n≤105。
思路:
令
f
(
i
)
=
1
i
2
f(i)=\frac{1}{i^2}
f(i)=i21
E
i
=
∑
j
=
0
i
−
1
q
j
f
i
−
j
−
∑
j
=
i
+
1
n
−
1
q
j
f
j
−
i
=
∑
j
=
0
i
q
j
f
i
−
j
−
∑
j
=
i
n
−
1
q
j
f
j
−
i
\begin{aligned} E_i&=\sum_{j=0}^{i-1}q_jf_{i-j}-\sum_{j=i+1}^{n-1}q_jf_{j-i}\\ &=\sum_{j=0}^{i}q_jf_{i-j}-\sum_{j=i}^{n-1}q_jf_{j-i}\\ \end{aligned}
Ei=j=0∑i−1qjfi−j−j=i+1∑n−1qjfj−i=j=0∑iqjfi−j−j=i∑n−1qjfj−i
可以定义
f
0
=
0
f_0=0
f0=0,然后把
q
j
q_j
qj映射到
Q
n
−
1
−
j
Q_{n-1-j}
Qn−1−j。则前面的就是卷积,可以用
F
F
T
FFT
FFT算,系数就是数组
q
,
f
q,f
q,f,取第
i
i
i项。对于后面的式子有
∑
j
=
i
n
−
1
Q
n
−
1
−
j
f
j
−
i
令
t
=
j
−
i
=
∑
t
=
0
n
−
1
−
i
Q
n
−
1
−
t
−
i
f
t
\begin{aligned} &\sum_{j=i}^{n-1}Q_{n-1-j}f_{j-i}\quad 令t=j-i\\ =&\sum_{t=0}^{n-1-i}Q_{n-1-t-i}f_{t}\\ \end{aligned}
=j=i∑n−1Qn−1−jfj−i令t=j−it=0∑n−1−iQn−1−t−ift
然后也可以用卷积算,注意系数是数组
Q
,
f
Q,f
Q,f,而且取第
n
−
1
−
i
n-1-i
n−1−i项。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const double Pi=acos(-1.0);
const int N=300009;
struct com
{
double x,y;
com(double xx=0,double yy=0)
{
x=xx,y=yy;
}
}a[N],aa[N],b[N],c[N],cc[N];
com operator + (com a,com b)
{
return com(a.x+b.x,a.y+b.y);
}
com operator - (com a,com b)
{
return com(a.x-b.x,a.y-b.y);
}
com operator * (com a,com b)
{
return com(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);
}
int n,m,bit=0,lim=1,r[N];
double sinn[N],coss[N];
void init()
{
while(lim<=2*n-1)
lim<<=1,bit++;
for(int i=1;i<lim;i<<=1)
sinn[i]=sin(Pi/i),coss[i]=cos(Pi/i);
for(int i=0;i<lim;i++)
r[i]=(r[i>>1]>>1)|((i&1)<<(bit-1));
}
void FFT(com *a,int type)
{
for(int i=0;i<lim;i++)
if(i<r[i])
swap(a[i],a[r[i]]);
for(int mid=1;mid<lim;mid<<=1)
{
com W(coss[mid],type*sinn[mid]);
for(int r=mid<<1,j=0;j<lim;j+=r)
{
com e(1,0);
for(int k=0;k<mid;k++,e=e*W)
{
com x=a[j+k],y=e*a[j+k+mid];
a[j+k]=x+y,a[j+k+mid]=x-y;
}
}
}
if(type==-1)
for(int i=0;i<lim;i++)
a[i].x/=lim;
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%lf",&a[i].x),aa[n-1-i].x=a[i].x;//映射
b[0].x=0.0;
for(int i=1;i<n;i++)
b[i].x=1.0/i/i;
init();
FFT(a,1),FFT(b,1),FFT(aa,1);
for(int i=0;i<lim;i++)
c[i]=a[i]*b[i],cc[i]=aa[i]*b[i];
FFT(c,-1),FFT(cc,-1);
for(int i=0;i<n;i++)
printf("%.3lf\n",c[i].x-cc[n-1-i].x);//后面取n-1-i项
return 0;
}