gamble 题解报告

发布时间 2023-12-15 23:49:01作者: 皮皮的橙子树
# Galble 题解

简要题意:
    给定一个数 $n$ AB两人赌博,每次你作为第三者下注任意整数 $x$ 元,A赢则获得 $x$ 元,否则亏损 $x$ 元。任何一个人赢 $n$ 次立刻结束游戏。你需要每次基于现在的情况,计算下的赌注,以使得在整个赌博的全过程,如果A胜利则获得 $2^{2n-1}$ 元,否则亏损这么多。给定一个01序列表示真实的AB两人的胜负情况(长度可能小于 $2n-1$ ,保证合法),你需要输出和01序列长度相同的数列,第i个数字表示在只知道前 $i-1$ 场胜负的情况下这一轮的赌注,答案对 $998244353$ 取模。可以证明答案唯一且为整数。

## 做法1 重要的初步暴力和分析
经过简单分析,我们发现对于前若干轮,同一个大局下(只关心A和B赢的场数)来说,我们手上的钱应该是确定的,虽然这个比较奇怪但是你考虑一个dp:

考虑 $dp_{i,j}$ 表示 $A$赢了 $i$ 场,$B$赢了 $j$ 场,表示手上有这么多钱,假设你投进去了 $x$ 元,输了就能构建等式 $dp_{i,j} = dp_{i,j+1}-x$ ,赢了构建等式 $dp_{i,j} = dp_{i+1,j}+x$ ,把 $x$ 消去,所以有 $2dp_{i,j} = dp_{i,j+1}+dp_{i+1,j}$ ,此时这个转移,根据题意有显然边界 $dp_{i,n} = -2^{2n-1}$,$dp_{n,j} = -2^{2n-1}$。

这个 $dp$ 直观说明了转移没有环,不需要神秘高消,而且是一步一步递推出来的,模拟这个过程,我们就有了一个 $O(n^2)$ 的做法。每一步的 $x$ 就是 $dp_{i,j+1} - dp_{i,j}$



## 做法2 暴力优化

考虑经典套路,把这种加法 $dp$ 拆组合数,具体的:


把每一个边界条件对答案的贡献拆开。

但是你会发现一个问题,我们dp里面有除二,所以还有乘上一个对应的 $2^{-len}$ ,$len$ 是路径长度,组合数大致形式是 $\sum_b \binom{a}{b} 2^{-b}$ 这种东西两个拼在一起。

但是显然这是一个经典的不可做的组合数类型因为你把 $2^{-b}$ 换成以1为底,都已经弥足困难,更别说一般化成3或者其他数字了。

考虑问题的特殊性:

- 这里是 2 ,而不是其他数字
- 这里是两个这种东西作差

对于第二个特殊性,我们可以考虑等会作差抵消一些不好算的东西。

对于对一个,我们可以这样:

 

把 $dp$ 数组强行补全,你会发现一个点到一些 $a/-a$ 的距离不变了,你这个2的指数就不见了,非常好,我们似乎接近正解了。

考虑作差会消掉什么,你可以公式推导,也可以直接在图片上看,$dp_{i,j+1} - dp_{i,j}$有什么不同和相同的地方。

具体的是:

$ \begin{aligned}
ans&=dp_{i,j+1} - dp_{i,j}\\
&=2^{2n-(X+Y)}\sum_{i=l}^{r-1}\binom{r-l}{i-l}a_i - 2^{2n-(X+Y)+1}\sum_{l}^{r-1}\binom{r-l-1}{i-l}a_i\\
\end{aligned} $

这诱导我们把组合数拆开,然后你就发现,变成 做法3 里面的东西了

## 做法3 做法2推导过程再优化

首先是 $dp$ 设计方面,我们刚刚设 $X = n-i,Y = n-j$ ,可以直接设 $dp_{X,Y}$,其实在 $dp$ 一开始转移的时候就应该立马注意到这个问题是倒着转移的,反过来就能更加方便。

然后是dp初始值的改进。不同的 $n$ 有不同的初始值,这是我们不希望看见的,一个显然的观察是你可以成倍数缩放整个 $dp$ 数组,把初始值改为 1 , 这样,配合上刚刚的操作,不同的 $n$ 的 $dp$ 数组就统一在一起了,他们共用一个 $dp$ 数组,这可太好了!

以及,这个问题是对称,我们就尽量不要破坏对称性。刚刚的推导有一步破坏了对称性,就是计算 $dp_{i,j+1} - dp_{i,j}$ 的时候。这里更好的写法是 $(dp_{i,j+1} - dp_{i+1,j})/2$

改进了这几点,我们沿着做法2继续推导,

 

这两个方块的位置相减,你对应到每一个贡献它的边界上面去,大多数抵消了,只有一对 1和-1交界处不抵消,此时我们答案就是一个单独的组合数,计算即可。

如果想在考场游刃有余,平时还需要多琢磨公式拆解的组合意义。
## 做法4 后记

如果你有足够的运气和数感,也可以利用做法1打表找规律,因为式子很简单,这个方法是管用的,核心观察其实是合数和质因数分解,当答案数字倾向于合数而不是质数的时候,就应该考虑是不是组合数或者什么东西乘在一起,或者某个有公因式的结构,把式子拆开。