【BZOJ1011】【HNOI2008】遥远的行星(乱搞)
1011: [HNOI2008]遥远的行星
Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 1444 Solved: 465
[Submit][Status]
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.
1< a < =3.5 接下来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%,也算对
Source
这题太太太太太太太太太太太神了!!!!!!!!!!!!!!!!!!!
核心在这http://hi.baidu.com/zeonsgtr/item/789da6f2838a3dc742c36ab7
我在这想重点说下思路:
这题思路就是枚举+乱搞,充分利用5%的误差。
对于小的数据n^2暴力,然后对于大的数据探索f[i]和f[i-t]的线性关系,可以得出一个近似的递推式子,这样就可以把1~i变为1~i-t和i-t+1~i
注意:(本题用实数实现的众多细节)
1、整数存到实数变量中要*1.0
2、取整的时候由于精度问题要加上一个1e-8,及(int)(1e-8+floor(a*i))
3、输出时候保留6位小数
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstring> 5 using namespace std; 6 const int maxn=100000,t=100; 7 const double eps=1e-8; 8 double a,f[maxn+50]; 9 int m[maxn+50],n; 10 int main() 11 { 12 scanf("%d %lf",&n,&a); 13 for(int i=1;i<=n;++i) scanf("%d",&m[i]); 14 for(int i=1;i<=t;++i) 15 { 16 f[i]=0.0; 17 int r=(int)(eps+floor(a*i)); 18 for(int j=1;j<=r;++j) f[i]+=1.0*m[i]*m[j]/(i-j); 19 } 20 for(int i=t+1;i<=n;++i) 21 { 22 int l=(int)(eps+floor(a*(i-t))); 23 int r=(int)(eps+floor(a*i)); 24 f[i]=0.0; 25 for(int j=l+1;j<=r;++j) f[i]+=1.0*m[i]*m[j]/(i-j); 26 f[i]+=1.0*m[i]*(f[i-t]/m[i-t])*(i-t-1.0*l/2)/(i-1.0*l/2); 27 } 28 for(int i=1;i<=n;++i) printf("%.6lf\n",f[i]); 29 return 0; 30 }
(我会说我叫了4次WA吗!!!那是我文件没去……orz我的AC率)