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
3
5
6
2
4
Sample Output
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.