题目:传送门
题意:给一个整数 n (1 <= n <= 18),输入 2^n 个数,编号为 0~2^n - 1(即数组 c ),起初有一个整数 statu,它的前 n 位二进制位都等于 -1,现在有A和B两人,共操作 n 次,每次操作等概率选择 satu 一个二进制位为 -1 的位,将它变为 0 或者1,最终得到 c[statu] 的值, A 想让这个值尽可能大, B 想让这个值尽可能小。现在有 r (0 <= r <= 2^18) 次修改,每次修改操作输入两个数, x,val,表示将 c[x] 重新赋值为 val,输出 r + 1 行,分别表示,最终得到的值的期望。
思路:因为 A 和 B 想要的是相反的,那么每个二进制位等于 0 和等于 1 的概率是相等的,每个数字被取到的概率也是相等的,即 statu 等于 [ 0, 2^n - 1 ] 的概率是相等的,最终每个 c[i] 被取到的概率都是 1 / 2^n,答案就是相当于求平均值。
#include <bits/stdc++.h> #define LL long long #define mem(i, j) memset(i, j, sizeof(i)) #define rep(i, j, k) for(int i = j; i <= k; i++) #define dep(i, j, k) for(int i = k; i >= j; i--) #define pb push_back #define make make_pair #define INF INT_MAX #define inf LLONG_MAX #define PI acos(-1) using namespace std; const int N = 1e6 + 5; int a[N]; int main() { int n, r; scanf("%d %d", &n, &r); LL ans = 0LL; rep(i, 0, (1 << n) - 1) scanf("%d", &a[i]), ans += a[i]; printf("%.8f ", (double)((double)(ans) / (double)((1 << n)))); rep(i, 1, r) { int x, val; scanf("%d %d", &x, &val); ans -= a[x]; a[x] = val; ans += a[x]; printf("%.8f ", ((double)(ans) / (double)((1 << n)))); } return 0; }