• P3198 [HNOI2008]遥远的行星


    传送门

    发现 $A$ 不大,又允许较大的误差,考虑乱搞

    考虑求出每个位置的答案,因为有 $1e5$ 个位置,所以每个位置差不多可以计算 $100$ 次贡献 

    所以把每个可以贡献的位置尽量均匀分成 $100$ 个块,同一个块内答案一起算

    本来一个位置的贡献是 $m[i]m[j]/(i-j)$ ,那现在一个块的贡献就可以看成 $m[i](sum[r]-sum[l-1])/(i-mid)$,就是把一段的贡献放在一起算,下标就取中位数

    这样误差就在 $5\%$ 以内了..

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    typedef double db;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=1e5+7,T=100;
    const db eps=1e-8;
    int n,a[N],sum[N];
    db A,ans[N];
    int main()
    {
        n=read(); scanf("%lf",&A);
        for(int i=1;i<=n;i++) a[i]=read(),sum[i]=sum[i-1]+a[i];
        for(int i=1;i<=n;i++)
        {
            int R=1.0*i*A+eps;
            if(!R) continue;
            if(R<=T) { for(int j=1;j<=R;j++) ans[i]+=1.0*a[i]*a[j]/(i-j); continue; }
            int l=1,r,p=R/T,t=R%T;
            for(int j=1;j<=T;j++)
            {
                r=l+p-(j>t);
                ans[i]+=1.0*a[i]*(sum[r]-sum[l-1])/(i-(l+r)/2);
                l=r+1;
            }
        }
        for(int i=1;i<=n;i++) printf("%.6lf
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    第4章 栈和队列
    第3章 线性表
    第2章 算法
    第1章 数据结构绪论
    First Blood
    第52条:通过接口引用对象
    第51条:当心字符串连接的性能
    第50条:如果其他类型更合适,则尽量避免使用字符串
    第49条:基本类型优先于装箱基本类型
    第48条:如果需要精确的答案,请避免使用float和double
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/11417637.html
Copyright © 2020-2023  润新知