点我查看题目
题目描述
给出n个数qi,给出Fj的定义如下:
F_j = \sum_{i<j}\frac{q_i q_j}{(i-j)^2 }-\sum_{i>j}\frac{q_i q_j}{(i-j)^2 }Fj=∑i<j(i−j)2qiqj−∑i>j(i−j)2qiqj
令Ei=Fi/qi,求Ei.
输入输出格式
输入格式:
第一行一个整数n。
接下来n行每行输入一个数,第i行表示qi。
输出格式:
n行,第i行输出Ei。
与标准答案误差不超过1e-2即可。
输入输出样例
输入样例#1: 复制
5 4006373.885184 15375036.435759 1717456.469144 8514941.004912 1410681.345880
输出样例#1: 复制
-16838672.693 3439.793 7509018.566 4595686.886 10903040.872
说明
对于30%的数据,n≤1000。
对于50%的数据,n≤60000。
对于100%的数据,n≤100000,0<qi<1000000000。
[spj 0.01]
思路:预处理C[i] = 1/(i*i)之后就是求卷积,右半部分只需要将Q数组反转,就能用卷积解决,FFT。
# include <bits/stdc++.h>
struct complex{
double x,y;
complex(double xx=0,double yy=0){x=xx;y=yy;}
complex operator +(const complex &b){return complex(b.x+x,b.y+y);}
complex operator -(const complex &b){return complex(-b.x+x,-b.y+y);}
complex operator *(const complex &b){return complex(x*b.x-y*b.y,x*b.y+y*b.x);}
}A[410010],B[410010],C[410010];
const double pi=acos(-1.0);
int n,limit=1,cnt=0,r[410010];
void fft(complex *a,double type){
int i,mid,j,k,R;complex w,wn,x,y;
for(i=0;i<limit;i++) if(i<r[i]) std::swap(a[i],a[r[i]]);
for(mid=1;mid<limit;mid<<=1){
wn=complex(cos(pi/mid),type*sin(pi/mid));
for(R=mid<<1,j=0;j<limit;j+=R){
w=complex(1,0);
for(k=0;k<mid;k++,w=w*wn){
x=a[j+k];y=w*a[j+k+mid];
a[j+k]=x+y;
a[j+k+mid]=x-y;
}
}
}
}
int main(){
scanf("%d",&n);
for(int i=1; i<=n; ++i){
scanf("%lf",&A[i].x);
B[n-i+1].x = A[i].x;
C[i].x = (1.0/(double)i)/(double)i;
}
while(limit<=(n<<1)) limit<<=1,cnt++;
for(int i=0;i<limit;i++) r[i]=((r[i>>1]>>1)|((i&1)<<(cnt-1)));
fft(A, 1);
fft(B, 1);
fft(C, 1);
for(int i=0; i<=limit; ++i) A[i] = A[i]*C[i], B[i] = B[i]*C[i];
fft(A, -1);
fft(B, -1);
for(int i=1; i<=n; ++i){
double tmp = A[i].x/limit - B[n-i+1].x/limit;//整数要加0.5再取整
printf("%.4f\n",tmp);
}
}