1011: [HNOI2008]遥远的行星
Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 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
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%,也算对
题目链接:
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.