【BZOJ1011】[HNOI2008]遥远的行星
【BZOJ1011】[HNOI2008]遥远的行星
题面
题解
乱搞题。。。
主要是要利用“只要结果的相对误差不超过5%即可”这个条件。
对于第\(i\)个行星,我们记\(x=\lfloor a*i\rfloor\),对他有贡献的区间为\([1,x]\)。
我们统计时,将区间\([1,x]\)分块统计,设块大小为\(len\)。
当\(x\leq len\),暴力即可。
当\(x>T\),将\([1,x]\)分为很多小区间,则每个小区间\([x,y]\)的贡献可看作
\[\frac{M_i*\sum_{j=x}^yM_j}{i-\frac{x+y}{x}}
\]
由于\(0.01<a\leq 0.35\),可知误差不超过\(0.02\)???(雾。。。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long double real;
const int MAX_N = 1e5 + 5, LEN = 320;
int N;
real A, M[MAX_N], sum[MAX_N];
int main () {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin);
#endif
scanf("%d%Lf", &N, &A);
for (int i = 1; i <= N; i++) scanf("%Lf", M + i);
for (int i = 1; i <= N; i++) {
sum[i] = sum[i - 1] + M[i];
real ans = 0;
int r = i * A;
for (int j = r; j > max(r - LEN, 0); j--) ans += M[i] * M[j] / (i - j);
if (r > LEN) {
r -= LEN;
int t = sqrt(r), l;
while (r) {
l = max(r - t, 0);
ans += M[i] * (sum[r] - sum[l]) / (i - (r + l) / 2);
r = l;
}
}
printf("%0.5Lf\n", ans);
}
return 0;
}