【BZOJ1011】[HNOI2008]遥远的行星

【BZOJ1011】[HNOI2008]遥远的行星

题面

bzoj

洛谷

题解

乱搞题。。。

主要是要利用“只要结果的相对误差不超过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; 
} 
posted @ 2019-03-19 22:32  heyujun  阅读(228)  评论(2编辑  收藏  举报