BZOJ-1011&洛谷P3198遥远的行星【HNOI2008】-玄学题之分块
作者:互联网
Time Limit: 10 Sec Memory Limit: 162 MBSec Special Judge
洛谷:时间限制1.00s 内存限制125.00MB
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1011
洛谷:https://www.luogu.com.cn/problem/P3198
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.33
5
6
2
4
Sample Output
0.0000000.000000
0.000000
1.968750
2.976000
HINT
精确结果应该为0 0 0 2 3,但样例输出的结果误差不超过5%,也算对
如果数据范围小一些的话就很好办,就是简单的暴力,我们先写出来:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int mac=1e5+10; int m[mac]; double f[mac]; int main() { int n; double a; scanf ("%d%lf",&n,&a); for (int i=1; i<=n; i++) scanf("%d",&m[i]); for (int i=1; i<=n; i++) f[i]=0; for (int i=1; i<=n; i++){ for (int j=1; j<=(int)i*a; j++){ f[i]+=1.0*m[i]*m[j]/(1.0*i-j); } } for (int i=1; i<=n; i++) printf("%f\n",f[i]); return 0; }
然后交一发就会发现只过了2个点。
然后。。。怎么优化,发现好像不会,就无耻地打开了题解。。。神TM近似解。
按照题解的算法来讲就是分块,由于有5%的误差,所以我们可以用块的中点来代替整个块,块越大误差越大,那么块中的答案就是$\frac {m[i]\times \sum_{j=l}^{r}m[j]} {i-(l+r)/2}$
数列分块的具体方法在我以前的博客中有过说明:https://blog.csdn.net/qq_43906000/article/details/100435873
以下是AC代码:
#include <bits/stdc++.h> using namespace std; #define ll long long const int mac=1e5+10; const double esp=1e-5; int m[mac],id[mac],L[mac],R[mac]; ll sum[mac]; double solve(int r,int p) { int rr=id[r]; double ans=0; if (rr==1){ for (int i=1; i<=r; i++) ans+=(double)m[i]*m[p]/(p-i); } else{ for (int i=1; i<=rr-1; i++) ans+=(double)m[p]*sum[i]/(p-(double)(R[i]+L[i])/2); for (int i=L[rr]; i<=r; i++) ans+=(double)m[p]*m[i]/(p-i); } return ans; } int main() { int n; double a; scanf ("%d%lf",&n,&a); for (int i=1; i<=n; i++) scanf("%d",&m[i]); int len=pow(n,0.35)+esp; int t=n/len; for (int i=1; i<=t; i++){ L[i]=(i-1)*len+1; R[i]=i*len; } if (R[t]<n) t++,L[t]=R[t-1]+1,R[t]=n; for (int i=1; i<=t; i++) for (int j=L[i]; j<=R[i]; j++) id[j]=i,sum[i]+=m[j]; for (int i=1; i<=n; i++){ int r=i*a+esp; double ans=solve(r,i); printf("%lf\n",ans); } return 0; }
标签:洛谷,0.000000,int,double,P3198,mac,HNOI2008,行星,include 来源: https://www.cnblogs.com/lonely-wind-/p/12217361.html