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

Solution

什么鬼题……省选考这种题真的大丈夫?

观察下式子,假设$p$是能对当前点$i$产生影响的最靠右位置,

$ans_i=\sum_{j=1}^{p} \frac{M_i \times M_j}{i - j}$。

发现当$i$小的时候,我们是可以暴力的。

当$i$大的时候,根据“只要结果的相对误差不超过$5\%$即可”这句话,我们可以发现,分母是非常大的!也就是对答案的贡献非常小。

对$j$我们完全可以统一取个近似值来算,反正不超过误差就行……近似值取$\frac{p}{2}$就行了……随便用个什么前缀和的算一下……

Code

 1 #include<iostream>
 2 #include<cstdio>
 3 #define N (100009)
 4 using namespace std;
 5 
 6 int n;
 7 double a,M[N],sum[N];
 8 
 9 int main()
10 {
11     scanf("%d%lf",&n,&a);
12     for (int i=1; i<=n; ++i)
13     {
14         int p=(int)(a*i+1e-8);
15         double ans=0;
16         scanf("%lf",&M[i]);
17         if (i<=1000) for (int j=1; j<=p; ++j) ans+=M[j]*M[i]/(i-j);
18         else ans=sum[p]*M[i]/(i-p/2);
19         printf("%.10lf\n",ans);
20         sum[i]=sum[i-1]+M[i];
21     }
22 }

 

posted @ 2019-03-01 11:49  Refun  阅读(200)  评论(0编辑  收藏  举报