BZOJ 1011--[HNOI2008]遥远的行星(乱搞)

时间:2022-02-09 00:53:39

1011: [HNOI2008]遥远的行星

Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge
Submit: 5684  Solved: 2135
[Submit][Status][Discuss]

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%,也算对

 

题目链接:

    http://www.lydsy.com/JudgeOnline/problem.php?id=1011 

Solution

  设mx [ i ] =A*i

  ans [ i ] = (M [ i ] * M [ j ] / ( i - j ) ) (1<=j<=mx [ i ]) 

  暴力显然是O(n^2)的。。。

  但是有没有什么好的算法。。。只能乱搞。。。

  当i<=2000时,可以暴力算。。。

  否则我们假装所有的( i - j )是相等的。。。即给所有合法的(i-j)取平均值。。。

  就可以O(1)的估计答案了。。。

  允许的误差范围很大,所以可以过。。

代码

#include<iostream>
#include<cstdio>
using namespace std;
int n;
double a;
double m[100010];
double m2[100010];
int main(){
    double ans=0,mx2,x;
    int mx;
    scanf("%d%lf",&n,&a);
    for(int i=1;i<=n;i++){
        scanf("%lf",&m[i]);
        m2[i]=m2[i-1]+m[i];
    }
    int k=min(n,2000);
    for(int i=1;i<=k;i++){
        ans=0;
        mx=(int)(a*(double)i+1e-8);
        for(int j=1;j<=mx;j+=1.0)
            ans=ans+(m[j]/(double)(i-j));
        printf("%0.6lf\n",ans*m[i]);
    }
    for(int i=k+1;i<=n;i++){
        ans=0;
        mx=(int)(a*(double)i+1e-8);
        ans=m2[mx]/(i-(mx/2))*m[i];
        printf("%0.6lf\n",ans);
    }
    return 0;
}

  

  

This passage is made by Iscream-2001.