1. 程式人生 > >[2019.1.7]BZOJ1011 [HNOI2008]遙遠的行星

[2019.1.7]BZOJ1011 [HNOI2008]遙遠的行星

如果 行星 -s 精度 clas 區間 它的 %d line

首先,我們都會暴力計算貢獻。

我們還發現這題對精度的要求很低。

於是我們心想,這一定不是出題人隨便放的,而是關乎正解的。

我們發現當\(j-i\)很大時,它的微小改變對答案的影響就是微不足道的。

於是我們定義一個塊大小\(siz\),然後對於一個長\(siz\)的區間\([i,i+siz-1]\),且這個區間位於影響\(F_j\)的取值的區間\([1,\lfloor Aj\rfloor]\)中,那麽我們近似地認為它們的貢獻之和為\(\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\n",Query(1,mx,i)*m[i]);
    return 0;
}

[2019.1.7]BZOJ1011 [HNOI2008]遙遠的行星