题目链接:力
听说这道题是(FFT)板子题,于是我就来写了……
首先可以发现这个式子:[E_i=sum_{j<i}frac{q_j}{(i-j)^2}-sum_{j>i}frac{q_j}{(i-j)^2} ]
然后可以对两半分别考虑一下。发现下标刚好是(j+(i-j)=i),于是我们就可以开始构(gao)造(shi)了,弄俩多项式出来:
[A_1(x)=0x^0+q_1x^1+q_2x^2+dots+q_nx^n]
[A_2(x)=frac{-1}{n^2}x^0+frac{-1}{(n-1)^2}x^1+dots+0x^n+dots+frac{1}{(n-1)^2}x^{2n-1}+frac{1}{n^2}x^{2n}]
把这两个多项式乘起来,取次数为((n,2n])的项前面的系数即为答案。
实际上,把多函数(A_1(x))的系数全部左移一位也是可以的,只不过答案的区间要跟着移一下。
下面贴代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<complex> #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) #define C complex<double> #define maxn 300010 #define pi (acos(-1)) using namespace std; typedef double llg; int n,m,L,R[maxn]; C a[maxn],b[maxn]; llg gi(int x){return 1.0*x*x;} void fft(C *a){ for(int i=0;i<n;i++) if(i<R[i]) swap(a[i],a[R[i]]); for(int i=1;i<n;i<<=1){ C wn(cos(pi/i),sin(pi/i)),x,y; for(int j=0;j<n;j+=(i<<1)){ C w(1,0); for(int k=0;k<i;k++,w*=wn){ x=a[j+k]; y=w*a[j+i+k]; a[j+k]=x+y; a[j+i+k]=x-y; } } } } int main(){ scanf("%d",&n); m=n; for(int i=0;i<n;i++) scanf("%lf",&a[i].real()); for(int i=0;i<n;i++) b[i].real()=-1.0/gi(n-i),b[2*n-i]=-b[i]; for(n=1;n<=(m<<1);n<<=1) L++; for(int i=0;i<n;i++) R[i]=(R[i>>1]>>1)|((i&1)<<(L-1)); fft(a); fft(b); for(int i=0;i<n;i++) a[i]*=b[i]; fft(a); reverse(a+1,a+n); for(int i=m;i<(m<<1);i++) printf("%.6lf ",a[i].real()/n); return 0; }