• [BZOJ1011] [HNOI2008] 遥远的行星


    Description

      直线上N颗行星,X=i处有行星i,行星J受到行星I的作用力,当且仅当i<=AJ.此时J受到作用力的大小为 Fi->j=
    Mi*Mj/(j-i) 其中A为很小的常量,故直观上说每颗行星都只受到距离遥远的行星的作用。请计算每颗行星的受力
    ,只要结果的相对误差不超过5%即可.

    Input

      第一行两个整数N和A. 1<=N<=10^5.0.01< a < =0.35,接下来N行输入N个行星的质量Mi,保证0<=Mi<=10^7

    Output

      N行,依次输出各行星的受力情况

    Sample Input

    5 0.3
    3
    5
    6
    2
    4

    Sample Output

    0.000000
    0.000000
    0.000000
    1.968750
    2.976000

    HINT

      精确结果应该为0 0 0 2 3,但样例输出的结果误差不超过5%,也算对 

    Source

    Solution

      按题意模拟,复杂度是$O(an^2)$的,然而好像并没有什么优化方法

      突破口是“误差不超过5%”这句话

      令$i=lfloor{aj} floor$

      对于星球$j$,我们要求的和式为$displaystylesum_{k=1}^{i}frac{m_k*m_j}{j-k}$

      当$j$很大时,$i$也不会太大,我们可以把式子化成$displaystylesum_{k=1}^{i}frac{m_k*m_j}{j-0.5i}$

      用$sum_i$表示前$i$个星球的质量和,那么和式可以化成$displaystylefrac{sum_i*m_j}{j-0.5i}$

      这样我们就可以少用一个变量$k$,复杂度就降为了$O(n)$

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 double m[100005], sum[100005];
     4 int main()
     5 {
     6     int n;
     7     double a, ans;
     8     scanf("%d%lf", &n, &a);
     9     for(int j = 1; j <= n; ++j)
    10     {
    11         int i = (int)(a * j + 1e-8);
    12         scanf("%lf", m + j);
    13         ans = 0;
    14         if(j <= 500)
    15             for(int k = 1; k <= i; ++k)
    16                 ans += m[k] * m[j] / (j - k);
    17         else
    18             ans = sum[i] * m[j] / (j - i / 2);
    19         printf("%f
    ", ans);
    20         sum[j] = sum[j - 1] + m[j];
    21     }
    22     return 0;
    23 }
    View Code
  • 相关阅读:
    win8设置无线网络共享
    设计模式学习每天一个——Decorator模式
    【转】命令模式(command pattern)
    设计模式总览
    设计模式学习每天一个——Command模式
    设计模式学习每天一个——Observer模式
    【转】UML解惑:图说UML中的六大关系
    设计模式学习每天一个——Strategy模式
    深入学习
    设计模式学习每天一个——Singleton模式
  • 原文地址:https://www.cnblogs.com/CtrlCV/p/5615585.html
Copyright © 2020-2023  润新知