#61. 连续段的期望

Description

内部题目,不放链接了。

Solution

emm乍一看,感觉一点思路都没有。\(or\)\(and\) 的期望怎么算啊?\(xor\) 的期望又怎么算錒?

我们发现数字的每一位是互不干扰的,那就可以对于每一位分别处理。

然后对于 \(or\)\(and\)\(xor\) 分别计算一下每一位前缀能凑出多少个不同的有贡献区间。

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#define ll long long

using namespace std;

const int N = 1e5 + 10;
int n;
ll l1, l2, l3, sum;
int a[N], f1[N][35], f2[N][35], f3[N][35];
//f1:xor	f2:and		f3:or

int main(){
	scanf("%d", &n);
	for(int i = 1; i <= n; i++){
		scanf("%d", &a[i]);
		sum += a[i];
	}
	for(int i = 1; i <= n; i++)
		for(int j = 0; j < 31; j++){
			if((a[i] >> j) & 1) f1[i][j] = (i - 1 - f1[i - 1][j]) + 1, f2[i][j] = f2[i - 1][j] + 1, f3[i][j] = i;
			else f1[i][j] = f1[i - 1][j], f2[i][j] = 0, f3[i][j] = f3[i - 1][j];
			l1 += (1ll << j) * f1[i][j];
			l2 += (1ll << j) * f2[i][j];
			l3 += (1ll << j) * f3[i][j];
		}
	l1 = (l1 << 1) - sum;//区间可以反过来,i~i的区间被多算了一遍
	l2 = (l2 << 1) - sum;
	l3 = (l3 << 1) - sum;
	printf("%.3f %.3f %.3f\n", (double)(l1) / n / n, (double)(l2) / n / n, (double)(l3) / n / n);
	return 0;
}

End

posted @ 2021-09-25 23:46  xixike  阅读(45)  评论(0编辑  收藏  举报