【BZOJ】1011 遥远的行星

题意

直线上 n 颗行星,x=i处有行星 i ,行星j受到行星 i 的作用力,当且仅当i<=Aj,此时 j 受到作用力的大小为 Fij=Mi×Mjji,其中 A 为很小的常量,故直观上说每颗行星都只受到距离遥远的行星的作用。
请计算每颗行星的受力,只要结果的相对误差不超过5%即可.

1n105
0.01a0.35

分析

gi 表示第 i 颗行星受1 gi 行星的作用力,则第 i 颗行星受力

fi=j=1giMi×Mjij=Mij=1giMjij

直接计算 fi 的时间复杂度为 O(n) ,总的时间复杂度为 O(n2) ,很明显会超时。

题目中提及“只要结果的相对误差不超过5%即可”,说明我们求出的值不用特别的精确,那么就考虑用近似算法进行估算。

考虑用递推的方法,把所求尽可能凑出已知量。
假设我们已经求出

fi=Mij=1giMjij

fi+T=Mi+T(j=1giMjij×iji+Tj+j=gi+1gi+TMji+Tj)

对于括号内的第二部分,注意 g 值具有的单调性,所以总共O(n)可以解决。
关键处理好括号内的第一部分即可。

第一部分可以这样估算:

j=1giMjij×iji+TjfiMi×igi2i+Tgi2

所以

fi+TMi+T×(fiMi×igi2i+Tgi2+j=gi+1gi+TMji+Tj)

为了使答案更加精确,我们需求更多的准确值。
对于 iT ,我们直接用暴力算法求解。
对于 i>T ,我们用 fiT 来估算 fi
T 的取值应尽可能大,而且暴力算法不会超时。
我的T取了 1000

还有就是要注意取整不能直接用 int(Aj) ,可以使用 int(Aj+EPS) ,或者使用函数 floor(Aj)
浮点误差会导致答案错误。

小结

  • 给定很少输入 1 N的某个函数值的问题,通常有两种方法:直接求、递推

  • 浮点数取整直接用 (int)a 会因为浮点误差带来结果的偏差,应使用 floor(a) 更精确

  • 关于这类估算的问题
    ①特征:“结果的相对误差不超过5%”之类的话,再给个SPJ;
    ②原则:能精确尽可能精确
    ③对于不超时的精确部分,就让它保留,对于会超时的精确部分,才考虑估算
    ④在用递推的方法时,对于小数据可以先暴力求,对于大数据再估算
    ⑤估算的一种常见方法:取平均数、中位数、众数之类的。

代码

#include <cstdio>
#include <cmath>

const int N=100010;
const int T=1000;
const double EPS=1e-7;

int n;
double a;

double m[N];
int g[N];

double w[N];

int main(void)
{
    scanf("%d%lf",&n,&a);

    for (int i=1;i<=n;i++) scanf("%lf",&m[i]);
    for (int i=1;i<=n;i++) g[i]=floor(a*i);

    for (int i=1;i<=T;i++)
    {
        for (int j=1;j<=g[i];j++)
            w[i]+=m[j]/(i-j);
        w[i]*=m[i];
    }

    double tmp;
    for (int i=1;i<=n-T;i++)
    {
        tmp=0;
        tmp=tmp+w[i]*(i-g[i]/2)/m[i]/(i+T-g[i]/2);
        for (int j=g[i]+1;j<=g[i+T];j++) tmp=tmp+m[j]/(i+T-j);
        w[i+T]=tmp*m[i+T];
    }

    for (int i=1;i<=n;i++)
        printf("%0.6lf\n",w[i]);

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值