转换一下式子然后卷积就可以了
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> typedef long double ld; struct C{ ld x,y; inline C(ld a=0,ld b=0){x=a,y=b;} inline C operator * (const C&b)const{return C(x*b.x-y*b.y,x*b.y+y*b.x);} inline C operator + (const C&b)const{return C(x+b.x,y+b.y);} inline C operator - (const C&b)const{return C(x-b.x,y-b.y);} inline C operator / (const ld&b)const{return C(x/b,y/b);} }; const int maxn = 550100; int rev[maxn],lim; inline void init(int len){ lim=1; while(lim<len)lim<<=1; for(int i=1;i<lim;++i)rev[i]=rev[i>>1]>>1|(i%2*lim/2); } const ld pi = acosl(-1); inline void fft(C*a,int type){ for(int i=0;i<lim;++i)if(rev[i]>i)std::swap(a[i],a[rev[i]]); for(int mid=1;mid<lim;mid<<=1){ const C W(cosl(pi/mid),(sinl(pi/mid))); for(int j=0;j<lim;j+=mid+mid){ C w(1,0),*A1=a+j,*A2=a+mid+j; for(int k=0;k<mid;++k,++A1,++A2,w=w*W){ const C x = *A1,y=*A2*w; *A1=x+y,*A2=x-y; } } } if(!type){ for(int i=0;i<lim;++i)a[i] = a[i] / lim; std::reverse(a+1,a+lim); } } int n,m; C g[maxn],q[maxn],f[maxn]; C res1[maxn],res2[maxn]; int main(){ std::ios::sync_with_stdio(false),std::cin.tie(0); std::cin >> n; ld x; for(int i=1;i<=n;++i)std::cin >> x,q[i].x=x; for(int i=1;i<=n;++i)g[i].x=(ld)1/i/i; for(int i=1;i<=n;++i)f[i]=g[n+1-i]; init(n<<1|1); fft(q,1),fft(g,1),fft(f,1); for(int i=0;i<lim;++i)res1[i]=q[i]*g[i],res2[i]=q[i]*f[i]; fft(res1,0),fft(res2,0); for(int i=1;i<=n;++i) printf("%.18Lf\n",(res1[i]-res2[n+i+1]).x); }