首先,我们都会暴力计算贡献。
我们还发现这题对精度的要求很低。
于是我们心想,这一定不是出题人随便放的,而是关乎正解的。
我们发现当(j-i)很大时,它的微小改变对答案的影响就是微不足道的。
于是我们定义一个块大小(siz),然后对于一个长(siz)的区间([i,i+siz-1]),且这个区间位于影响(F_j)的取值的区间([1,lfloor Aj floor])中,那么我们近似地认为它们的贡献之和为(frac{sum_{x=i}^{i+siz-1}M_x}{frac{1}{2}[(j-i)+(j-i-siz+1)]})
也就是我们认为一个区间的(j-i)都是其中(j-i)的平均值。然后如果要求影响第(j)颗星球引力的星球区间([1,x])的引力和,我们对它分块计算,对于小于(siz)的区间暴力计算。
然后就过了。
code:
#include<bits/stdc++.h>
using namespace std;
const double _=1e-8;
const int blk=40;
int n,mx;
double a,m[100010],sum[100010];
double query(int l,int r,int f){
if(r<l)return 0;
double st=((f-l)*1.0+(f-r)*1.0)/2.0;
return (sum[r]-sum[l-1])/st;
}
double query1(int l,int r,int f){
if(r<l)return 0;
double ans=0;
for(int i=l;i<=r;i++)ans+=m[i]/(f-i*1.0);
return ans;
}
double Query(int l,int r,int f){
if(r<l)return 0;
double ans=0;
while(r-l+1>=blk)ans+=query(l,l+blk-1,f),l+=blk;
ans+=query1(l,r,f);
return ans;
}
int main(){
scanf("%d%lf",&n,&a);
for(int i=1;i<=n;i++)scanf("%lf",&m[i]);
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+m[i];
for(int i=1;i<=n;i++)mx=i*a+_,printf("%.5lf
",Query(1,mx,i)*m[i]);
return 0;
}