题目:BZOJ3527.
题目大意:给定一个长度为
n
n
n的
q
q
q数组,求:
E
j
=
∑
i
<
j
q
i
(
i
−
j
)
2
−
∑
i
>
j
q
i
(
i
−
j
)
2
E_j=\sum_{i<j}\frac{q_i}{(i-j)^2}-\sum_{i>j}\frac{q_i}{(i-j)^2}
Ej=i<j∑(i−j)2qi−i>j∑(i−j)2qi
其中 1 ≤ n ≤ 1 0 5 , 1 ≤ q i < 1 0 9 1\leq n\leq 10^5,1\leq q_i<10^9 1≤n≤105,1≤qi<109.
设
f
i
=
1
i
2
f_i=\frac{1}{i^2}
fi=i21,开始大力推式子:
E
j
=
∑
i
<
j
q
i
f
j
−
i
−
∑
i
>
j
q
i
f
i
−
j
=
∑
i
=
1
j
−
1
q
i
f
j
−
i
−
∑
i
=
j
+
1
n
q
i
f
i
−
j
E_j=\sum_{i<j}q_if_{j-i}-\sum_{i>j}q_if_{i-j}\\ =\sum_{i=1}^{j-1}q_if_{j-i}-\sum_{i=j+1}^{n}q_if_{i-j}
Ej=i<j∑qifj−i−i>j∑qifi−j=i=1∑j−1qifj−i−i=j+1∑nqifi−j
令
p
i
=
q
n
−
i
p_i=q_{n-i}
pi=qn−i,那么:
E
j
=
∑
i
=
1
j
−
1
q
i
f
j
−
i
−
∑
i
=
j
+
1
n
p
n
−
i
f
i
−
j
=
∑
i
=
1
j
−
1
q
i
f
j
−
i
−
∑
i
=
1
n
−
j
p
n
−
j
−
i
f
i
E_j=\sum_{i=1}^{j-1}q_if_{j-i}-\sum_{i=j+1}^{n}p_{n-i}f_{i-j}\\ =\sum_{i=1}^{j-1}q_if_{j-i}-\sum_{i=1}^{n-j}p_{n-j-i}f_{i}
Ej=i=1∑j−1qifj−i−i=j+1∑npn−ifi−j=i=1∑j−1qifj−i−i=1∑n−jpn−j−ifi
发现前后两个都是卷积形式,用FFT优化即可.时间复杂度 O ( n log n ) O(n\log n) O(nlogn).
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=262144;
const double pi=acos(-1);
struct comp{
double a,b;
comp(double A=0,double B=0){a=A;b=B;}
comp operator + (const comp &p){return comp(a+p.a,b+p.b);}
comp operator - (const comp &p){return comp(a-p.a,b-p.b);}
comp operator * (const comp &p){return comp(a*p.a-b*p.b,a*p.b+b*p.a);}
};
int n,m,len,rev[N+9];
comp pw[N+9],a[N+9],b[N+9],c[N+9];
double ans[N+9];
void Get_len(int n){
int l=0;
for (len=1;len<=n;len<<=1) ++l;
for (int i=0;i<len;++i) rev[i]=rev[i>>1]>>1|(i&1)<<l-1;
}
void FFT(comp *a,int n,int t){
for (int i=0;i<n;++i)
if (i<rev[i]) swap(a[i],a[rev[i]]);
for (int i=1;1<<i<=n;++i){
int len=1<<i;
comp wn=comp(cos(2.0*pi/len),sin(2.0*pi/len)*(t?-1:1));
pw[0]=comp(1,0);
for (int j=1;j<len>>1;++j) pw[j]=pw[j-1]*wn;
for (int j=0;j<n;j+=len)
for (int k=0;k<len>>1;++k){
comp x=a[j+k],y=pw[k]*a[j+k+(len>>1)];
a[j+k]=x+y;a[j+k+(len>>1)]=x-y;
}
}
}
Abigail into(){
scanf("%d",&n);
for (int i=1;i<=n;++i)
scanf("%lf",&a[i].a);
}
Abigail work(){
for (int i=0;i<=n;++i) b[i].a=a[n-i].a;
for (int i=1;i<=n;++i) c[i].a=1.0/i/i;
Get_len(n<<1);
FFT(a,len,0);
FFT(b,len,0);
FFT(c,len,0);
for (int i=0;i<len;++i) a[i]=a[i]*c[i],b[i]=b[i]*c[i];
FFT(a,len,1);
FFT(b,len,1);
for (int i=1;i<=n;++i) ans[i]=(a[i].a-b[n-i].a)/len;
}
Abigail outo(){
for (int i=1;i<=n;++i)
printf("%.3lf\n",ans[i]);
puts("");
}
int main(){
into();
work();
outo();
return 0;
}