SRM727Hard
题意
有 \(B\) 只熊和 \(H\) 个人。攻击 \(T\) 次,每次随机从没死的怪中选出一个,扣一滴血,血量为 \(0\) 就死。每头熊 \(2\) 滴血,每个人 \(1\) 滴血。
问 \(T\) 次攻击后 \(b\ \times\ h\ \times\ (b\ +\ h)\) 的期望是多少。\(b\) 表示没死的熊的数量,\(h\) 表示没死的人的数量。
\(1\ \leq\ H,\ B\ \leq\ 2000,\ 0\ \leq\ T\ \leq\ 2B\ +\ H\)
做法1
\(E(b\ \times\ h\ \times\ (b\ +\ h))\ =\ E(b^2\ h\ +\ b\ h^2)\ =\ E(b^2\ h)\ +\ E(b\ h^2)\)。
由于 \(b\) 和 \(h\) 不是独立的,不能将 \(E(b^2\ h)\) 拆成 \(E(b^2)\ E(h)\)。
令 \(P(x,\ y,\ z)\) 表示还剩下 \(x\) 个两血怪,\(y\) 个一血怪,\(z\) 个人的概率是多少。
所求即为 \(\sum_{x,\ y,\ z}\ P(x,\ y,\ z)\ ((x\ +\ y\ -\ z)\ z^2\ +\ (x +\ y\ -\ z)^2\ z)\ =\ \sum_{x,\ y,\ z}\ P(x,\ y,\ z)\ ((x\ +\ y)^2\ z\ -\ (x\ +\ y)\ z^2)\)。
我们令 \(E(x,\ y,\ 0)\ =\ \sum_{z}\ P(x,\ y,\ z)\ z,\ E(x,\ y,\ 1)\ =\ \sum_{z}\ P(x,\ y,\ z)\ z^2\),发现 \(E(x,\ y,\ 0/1)\) 可以 \(O(1)\) 转移。
总复杂度 \(O(n^2)\)。
代码
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
struct DoubleLive {
int findEV(int B, int H, int T) {
auto inv = [&](int x) {
int y = 1, n = mod - 2;
while(n) {
if(n & 1) y = (long long) y * x % mod;
x = (long long) x * x % mod;
n >>= 1;
}
return y;
};
vector<int> Mu(B + H + 1);
for (int i = 1; i < Mu.size(); ++i) Mu[i] = inv(i);
vector<vector<array<int, 2> > > E(B + 1);
E[B] = vector<array<int, 2> >(B + H + 1, array<int, 2>{0, 0});
E[B][H] = array<int, 2>{H, H * H};
int ans = 0;
for (int x = B; ~x; --x) {
if(x) E[x - 1] = vector<array<int, 2> >(B + H + 1, array<int, 2>{0, 0});
for (int y = B + H; ~y; --y) {
int mu = Mu[x + y];
if(y) {
E[x][y - 1][0] = ((long long) E[x][y][0] * (y - 1) % mod * mu + E[x][y - 1][0]) % mod;
E[x][y - 1][1] = ((long long) E[x][y][0] * mu + (long long) E[x][y][1] * (y - 2) % mod * mu + E[x][y - 1][1]) % mod;
}
if(x && y + 1 <= B + H) {
for (int i = 0; i < 2; ++i) E[x - 1][y + 1][i] = ((long long) E[x][y][i] * x % mod * mu + E[x - 1][y + 1][i]) % mod;
}
if(2 * x + y + T == 2 * B + H) {
ans = ((long long) -(x + y) * E[x][y][1] + (long long) (x + y) * (x + y) * E[x][y][0] + ans) % mod;
}
}
E[x].clear();
}
return (ans + mod) % mod;
}
};