P4050 麻将 题解
不愧是 ZJOI。
题意:有 \(n\) 种麻将牌,每种四张。定义 "胡牌" 为小鸡胡或普通七小对。给定初始 \(13\) 张牌,将剩下 \(4n-13\) 张牌随机排列,问期望摸多少张牌能胡(假设采用最优决策)。\(n\le 100\)。
先考虑怎么判定是否胡牌。
\(cnt[i]\) 表示前 \(i\) 种牌能凑出多少个对子,\(f[i][j][k]\) 表示前 \(i\) 种牌,预留 \(j\) 对 \((i-1,i)\) 和 \(k\) 张 \(i\) 的最大面子数,\(g[i][j][k]\) 表示前 \(i\) 种牌,预留 \(j\) 对 \((i-1,i)\) 和 \(k\) 张 \(i\) 和一个对子的最大面子数。若 \(g[][][]\ge 4\),说明胡了。
将 \((f[i][0\sim 2][0\sim 2],g[i][0\sim 2][0\sim 2],cnt[i])\) 共同视作一个状态。\(f,g\) 的 \(j,k\) 之所以在 \(0\sim 2\) 中,是因为如果预留了 \(3\) 对 \((i-1,i)\) 等待 \(i+1\) 组成三个顺子,可以视作 \(i-1,i,i+1\) 各自组成了刻子。
转移就枚举新来了多少张牌,看用多少张 \(i+1\)、和谁搭配进行转移。建立一个专门的 "胡牌状态",如果转移后发现胡了,转移到这个胡牌状态,然后停止转移。实践证明,有效状态 \(\le 2100\) 个。
因此可以把这些有效的状态都拿出来,建立自动机。
于是解决了判定胡牌的问题:等价于在自动机上走到胡牌状态。
回到原问题。令 \(x\) 为随机变量,表示第一次胡的时候摸了几张牌。
记 \(ans(j)\) 为从剩下 \(4n-13\) 张取 \(j\) 张(的组合),搭配前 \(13\) 张不胡的方案数。
则 \(Pr(\text{摸 j 张不胡})=\dfrac{ans(j)\cdot j!\cdot (4n-13-j)!}{(4n-13)!}\)。问题转变为求 \(ans(j)\)。
考虑问题的简化版:从 \(4n\) 张牌中选 \(j\) 张的组合,使得它们不胡的方案数。
这里就是 DP of DP 了。
换一种方式,我们不是决定下一次抽出什么牌,而是从小到大决定我们抽出几张牌。换句话说,令 \(a_i\) 为抽出 \(i\) 的张数,我们要求的是 \((a_1\sim a_n)\) 使得 \(\sum a_i=j\) 且不胡的方案数。
\(dp[i][j][k]\) 表示考虑 \(a_1\sim a_i\),此时 \(\sum a=j\),在自动机上走到状态 \(j\) 的方案数。转移时枚举 \(a_{i+1}\) 是多少。
回到原问题。令 \(b_i\) 表示前 \(13\) 张中有多少张是第 \(i\) 种牌,相当于:计数 \((a_1\sim a_n)\),使得 \(a_i\ge b_i,\sum (a_i-b_i)=j\),且不胡的方案数。
沿用上面的 DP 定义,只需要在转移时变成枚举 \(a_i-b_i\) 是多少即可。
本题卡常。在二重循环内部,每次调用一次组合数函数都会 TLE。必须在一重循环内提前把二重循环会用到的组合数存到数组里才不会 TLE。