【BZOJ1011】[HNOI2008]遥远的行星
题面
题解
乱搞题。。。
主要是要利用“只要结果的相对误差不超过5%即可”这个条件。
对于第(i)个行星,我们记(x=lfloor a*i floor),对他有贡献的区间为([1,x])。
我们统计时,将区间([1,x])分块统计,设块大小为(len)。
当(xleq len),暴力即可。
当(x>T),将([1,x])分为很多小区间,则每个小区间([x,y])的贡献可看作
[frac{M_i*sum_{j=x}^yM_j}{i-frac{x+y}{x}}
]
由于(0.01<aleq 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
", ans);
}
return 0;
}