Live2D

Solution -「LOCAL」舟游

\(\mathcal{Description}\)

  \(n\) 中卡牌,每种三张。对于一次 \(m\) 连抽,前 \(m-1\) 次抽到第 \(i\) 种的概率是 \(p_i\),第 \(m\) 次抽到第 \(i\) 种的概率是 \(q_i\)。若抽到第 \(i\) 种,会等概率地得到三张卡牌中的一张。求得到所有 \(3n\) 张卡的期望 \(m\) 连抽次数。对 \(2000000011\) 取模。

  \(n\le6\)\(m\le64\)

\(\mathcal{Solution}\)

  目睹 Tiw 踩标算,%%%

\(\mathcal{Case~1}\)

  长得就像状压期望 DP。令 \(f(S,i)\) 表示抽到的卡牌集合为 \(S\)(同种卡牌显然无序,用两个 bit 记录一种卡牌拥有的张数即可)。发现转移会有一个 \(f(S,1)\leftarrow f(S,2)\leftarrow\cdots\leftarrow f(S,m)\leftarrow f(S,1)\) 的大小为 \(m\) 的简单环。手动消元解出来就好。

  考 场 上 写 自 闭 了。

\(\mathcal{Case~2}\)

  长得就像 \(\text{Min-Max}\) 反演——Tiw。\(\text{Min-Max}\) 反演在期望意义下的式子长成:

\[E(\max_{\xi\in S}\{\xi\})=\sum_{T\subseteq S\land T\not=\varnothing}(-1)^{|T|-1}E(\min_{\xi\in T}\{\xi\}) \]

  其中 \(S\) 是随机变量集合。对于本题,我们相当于要求每张卡被抽到时间的最大值的期望,可以用上式反演成求每张卡被抽到时间的最小值的期望。为方便推式子,令 \(p\)\(q\) 的意义为抽到某一张卡的概率。对于某个具体的卡牌集合,就要求至少抽中 \(T\) 中一张卡牌的期望时间。那么:

\[E(\min_{\xi\in T}\{\xi\})=\frac{1}{\displaystyle 1-\left(1-\sum_{c\in T}p_c\right)^{m-1}\left(1-\sum_{c\in T}q_c\right)} \]

  枚举集合 \(T\),就做完了。(

  复杂度 \(\mathcal O(4^n\log 2000000011)\)

\(\mathcal{Code}\)

  Case 2.

/* Clearink */

#include <cstdio>

typedef long long LL;

const int MAXN = 9, MAXM = 64, MAXS = 1 << 18, MOD = 2000000011;
int n, m, ans, p[MAXN + 5], q[MAXN + 5];

inline int add ( LL a, const int b ) { return ( a += b ) < MOD ? a : a - MOD; }
inline int sub ( LL a, const int b ) { return ( a -= b ) < 0 ? a + MOD : a; }
inline int mul ( LL a, const int b ) { return ( a *= b ) < MOD ? a : a % MOD; }

inline int qkpow ( int a, int b ) {
	int ret = 1;
	for ( ; b; a = mul ( a, a ), b >>= 1 ) ret = mul ( ret, b & 1 ? a : 1 );
	return ret;
}

inline void solve ( const int id, const bool s, const int sump, const int sumq, const int ways ) {
	if ( id == n + 1 ) {
		int val = mul ( ways, qkpow (
			sub ( 1, mul ( qkpow ( sub ( 1, sump ), m - 1 ), sub ( 1, sumq ) ) ), MOD - 2 ) );
		ans = ( s ? add : sub )( ans, val );
		return ;
	}
	solve ( id + 1, s, sump, sumq, ways );
	solve ( id + 1, !s, add ( sump, p[id] ), add ( sumq, q[id] ), mul ( ways, 3 ) );
	solve ( id + 1, s, add ( sump, mul ( p[id], 2 ) ), add ( sumq, mul ( q[id], 2 ) ), mul ( ways, 3 ) );
	solve ( id + 1, !s, add ( sump, mul ( p[id], 3 ) ), add ( sumq, mul ( q[id], 3 ) ), ways );
}

int main () {
	freopen ( "arknights.in", "r", stdin );
	freopen ( "arknights.out", "w", stdout );
	scanf ( "%d %d", &n, &m );
	int rv = qkpow ( 300 * n, MOD - 2 );
	for ( int i = 1; i <= n; ++ i ) scanf ( "%d", &p[i] ), p[i] = mul ( p[i], rv );
	for ( int i = 1; i <= n; ++ i ) scanf ( "%d", &q[i] ), q[i] = mul ( q[i], rv );
	solve ( 1, 0, 0, 0, 1 );
	printf ( "%d\n", ans );
	return 0;
}
posted @ 2020-09-13 15:03  Rainybunny  阅读(241)  评论(0编辑  收藏  举报