#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;
}