上海市计算机 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;
}
 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号