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
3
5
6
2
4
Sample Output
0.000000
0.000000
0.000000
1.968750
2.976000
0.000000
0.000000
1.968750
2.976000
HINT
精确结果应该为0 0 0 2 3,但样例输出的结果误差不超过5%,也算对
题解
显然直接暴力枚举答案基本上是会T的,我们注意到了a的值并不是太大,并且答案误差在%5的范围内。那么原式可估算sum[x]*m[i]/(j-0.5i)。其中sum[i]为前i个星球的质量和。不过出这种题的人是什么心态啊……
代码
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #define maxn 100010 8 #define eps 1e-8 9 using namespace std; 10 int n,t; 11 double m[maxn],sum[maxn]; 12 double a,ans; 13 int main(){ 14 scanf("%d",&n); 15 scanf("%lf",&a); 16 int i,j; 17 for(i=1;i<=n;++i){ 18 scanf("%lf",&m[i]);sum[i]=sum[i-1]+m[i]; 19 } 20 for(i=1;i<=n;++i){ 21 ans=0; 22 int x=(int)(a*i+eps); 23 if(x<=500){ 24 for(j=1;j<=x;++j) ans+=m[j]*m[i]/(i-j); 25 } 26 else{ 27 ans=sum[x]*m[i]/(i-x/2); 28 } 29 printf("%.6lf\n",ans); 30 } 31 return 0; 32 }