上海市计算机 2023 年 1 月月赛 甲组T3

状态压缩 + 期望与概率 dp

我们用 \(dp_i\) 表示当前得到的礼品的状态为 \(i\),一直到拿到 \(n\) 个礼品的期望盲盒个数。

\[dp_i = \sum\limits_{j=1}^{n}dp_{i|j}\times \frac{p_j}{sum} + 1 \]

\[dp_i = dp_{i}\times \sum\limits_{j=1}^{n}[j\in i] \times\frac{p_j}{sum}+\sum\limits_{j=1}^{n}dp_{i|j}\times [j\notin i] \times\frac{p_j}{sum} + 1 \]

\(x = \sum\limits_{j=1}^{n}[j\in i]\times p_j\)

原式:

\[\begin{align} dp_i =& dp_{i}\times\frac{x}{sum}+\sum\limits_{j=1}^{n}dp_{i|j}\times [j\notin i] \times\frac{p_j}{sum} + 1\\ \frac{sum-x}{sum}\times dp_i =& \sum\limits_{j=1}^{n}dp_{i|j}\times [j\notin i] \times\frac{p_j}{sum} + 1\\ (sum-x)\times dp_i =& \sum\limits_{j=1}^{n}dp_{i|j}\times [j\notin i] \times sum + sum\\ dp_i =& \frac{\sum\limits_{j=1}^{n}dp_{i|j}\times [j\notin i] \times p_j + sum}{sum-x} \end{align} \]

这里下标是从 \(0\) 开始,为了方便位运算,不喜勿喷。

AcCode

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 20, P = 10007;
int n, sum;
int p[N], inv[2010], dp[1 << N];

int main() {
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		scanf("%d", &p[i]);
		sum += p[i];
	}
	inv[1] = 1;
	for (int i = 2; i <= sum; i++)
		inv[i] = (P - P / i) * inv[P % i] % P;
	for (int i = (1 << n) - 1; i >= 0; i--) {
		int x = 0;
		for (int j = 0; j < n; j++)
			if (i & (1 << j)) x += p[j];
		for (int j = 0; j < n; j++)
			if (!(i & (1 << j)))
				(dp[i] += dp[i | (1 << j)] * p[j] % P) %= P;
		(dp[i] += sum) %= P;
		dp[i] = dp[i] * inv[sum - x] % P;
	}
	printf("%d\n", dp[0]);
	return 0;
}
posted @ 2023-02-07 20:56  weirdoX  阅读(115)  评论(1)    收藏  举报