tyvj 2020 rainbow 的信号

期望

被精度坑惨的我

注意:能开 long long 尽量开, 先除后乘, int 转 double 的时候 先转换在做运算

本题与位运算有关,位与位之间互不影响,所以我们可以分开考虑

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
int init() {
	int rv = 0, fh = 1;
	char c = getchar();
	while(c < '0' || c > '9') {
		if(c == '-') fh = -1;
		c = getchar();
	}
	while(c >= '0' && c <= '9') {
		rv = (rv<<1) + (rv<<3) + c - '0';
		c = getchar();
	}
	return fh * rv;
}
int n, num[100005], lst[2], c1, c0;
double bas, ans1, ans2, ans3;
void solve(int j) {
	for(int i = 1; i <= n; i++) {
		if(num[i] & (1 << j)) {
			ans1 += (1 << j) * bas;
			ans2 += (1 << j) * bas;
			ans3 += (1 << j) * bas;
		}
	}
	//printf("%.3f %.3f %.3f\n", ans3, ans1, ans2);
	lst[0] = lst[1] = c0 = c1 = 0;
	for(int i = 1;i <= n; i++) {
		if(num[i] & (1 << j)) {
			ans1 += (1 << j) * 2.0 * bas * (i - lst[0] - 1); // 先变后乘
			ans2 += (1 << j) * 2.0 * bas * (i - 1);
			ans3 += (1 << j) * 2.0 * bas * c1;
			lst[1] = i;
		}else {
			ans2 += (1 << j) * 2.0 * bas * lst[1];
			ans3 += (1 << j) * 2.0 * bas * c0;
			lst[0] = i;
		}
		c1++;
		if(num[i] & (1 << j)) swap(c1, c0);
	}
	//printf("%.3f %.3f %.3f\n", ans3, ans1, ans2);
}
int main() {
	n = init();
	for(int i = 1; i <= n; i++) num[i] = init();
	bas = (double) 1.0 / n / n;
	for(int j = 0; j < 31; j++) {
		solve(j);
	}
	printf("%.3f %.3f %.3f\n", ans3, ans1, ans2);
	return 0;
}
posted @ 2018-03-25 21:43  Mr_Wolfram  阅读(168)  评论(0编辑  收藏  举报