[HNOI2008]遥远的行星

题目描述

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

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1: 复制
5 0.3
3
5
6
2
4
输出样例#1: 复制
0.000000
0.000000
0.000000
1.968750
2.976000

说明

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

一开始以为要高级数据结构,其实可以不要

问题实际在于要除以(i-j)

重点在于误差不超过5%

所以我们可以估读

当A×i小于100时,可以枚举

A×i大于100,可以把[1,x]分成100份[li,ri]

那么每个区间内的所有力的和就可以估读

ans+=d[i]*(s[ri]-s[li-1])/(i-(ri-li)/2)

也就是把所有的1/(i-j)≈1/(i-(ri-li)/2)

因为0.01<=A<=0.35,所以5%的误差差不多

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 double A,ans[100001],d[100001],sum[100001];
 7 int n;
 8 int main()
 9 {int i,j;
10     cin>>n>>A;
11     for (i=1;i<=n;i++)
12     {
13         scanf("%lf",&d[i]);
14         sum[i]=sum[i-1]+d[i];
15     }
16     for (i=1;i<=n;i++)
17     {
18         int x=i*A;
19         if (x>100)
20         {
21             int lim=x/100; 
22             for (j=lim;j<=lim*100;j+=lim)
23             {
24              double mid=(2*i-2*j+lim-1)*0.5;
25              ans[i]+=d[i]*(sum[j]-sum[j-lim])/mid;
26             }
27             for (j=lim*100+1;j<=x;j++)
28             ans[i]+=d[i]*d[j]/(i-j);
29         }
30         else if (x<=100&&x)
31         {
32             for (j=1;j<=x;j++)
33             ans[i]+=(d[i]*d[j]/(i-j));
34         } 
35     }
36     for (i=1;i<=n;i++)
37     printf("%.6lf\n",ans[i]);
38 }

 

posted @ 2017-12-23 19:28  Z-Y-Y-S  阅读(248)  评论(0编辑  收藏  举报