题目简述:
我们令
Fj=∑i<jqiqj(i−j)2−∑i>jqiqj(i−j)2
Ei=Fiqi
然后求 Ei
题解:
题目的名字还真是生动形象。。
看到 i<j 就想到了熟悉的卷积形式
于是把两边分开求
构造俩长度为2n的
首先设:
Ai=−1(n−i)2(当i<n)Ai=1(n−i)2(当i>n)
Bi=qi
然后把 A 和
对于
当 j<i 时,它加上的是 AjBn+i−j ,这时 n+i−j>n , Bn+i−j 为正,而这就是前面那坨东西
同理,当 j>i 时, n+i−j<n , Bn+i−j 为负,这就是后面那坨东西。
所以构造俩多项式乘一下就完了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const int inf=0x3f3f3f3f;
const db pi=3.1415926535897932384626;
int getint()
{
int f=1,g=0;char c=getchar();
while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0' && c<='9')g=(g<<3)+(g<<1)+c-'0',c=getchar();
return f*g;
}
const int maxn=1000005;
struct comp{
db re,im;
comp(){}
comp(db re,db im):re(re),im(im){}
comp operator + (const comp &poi)const {return comp(re+poi.re,im+poi.im);}
comp operator - (const comp &poi)const {return comp(re-poi.re,im-poi.im);}
comp operator * (const comp &poi)const {return comp(re*poi.re-im*poi.im,re*poi.im+im*poi.re);}
};
int rev[maxn];
int n;
db q[maxn];
int len;
comp a[maxn],b[maxn],c[maxn];
void fft(comp *a,int n,db f)
{
for(int i=0;i<n;i++)
{
if(i>rev[i])
{
swap(a[i],a[rev[i]]);
}
}
comp w,wn,temp1,temp2;
int mid;
for(int i=2;i<=n;i<<=1)
{
wn=comp(cos(2.0*pi/i*f),sin(2.0*pi/i*f));
mid=i>>1;
for(int j=0;j<n;j+=i)
{
w=comp(1.0,0);
for(int k=0;k<mid;k++)
{
temp1=a[j+k];
temp2=a[j+k+mid]*w;
a[j+k]=temp1+temp2;
a[j+k+mid]=temp1-temp2;
w=w*wn;
}
}
}
if(f==-1)
{
for(int i=0;i<n;i++)
{
a[i].re/=n;
}
}
}
db sqr(db x){return x*x;}
int main()
{
// freopen("in.txt","r",stdin);
n=getint();
for(int i=0;i<n;i++)
{
scanf("%lf",&a[i].re);
}
int tn=n;
for(int i=0;i<tn;i++)
{
b[i].re=-(1.0/sqr(n-i));
}
for(int i=tn+1;i<=tn*2;i++)
{
b[i].re=1.0/sqr(i-n);
}
int m=1;
len=0;
n=n*2+1;
while(m<n)m<<=1,len++;
n=m;
for(int i=0;i<n;i++)
{
int temp=i;
int pos=0;
for(int j=1;j<=len;j++)
{
pos<<=1;pos|=temp&1;temp>>=1;
}
rev[i]=pos;
}
fft(a,n,1);
fft(b,n,1);
for(int i=0;i<n;i++)
{
c[i]=a[i]*b[i];
}
fft(c,n,-1);
for(int i=0;i<tn;i++)
{
printf("%lf\n",c[i+tn].re);
}
return 0;
}