上帝掷硬币的智力题,从 9 胜 6 开始的深入研究

最近看到一道智力题,大意如下:

上帝让 Alice 和 Bob 两人玩一个猜硬币游戏。猜硬币共进行 13 轮,每轮上帝将硬币盖在手下,让 Alice 和 Bob 分别猜硬币是正面还是反面。两人各自独立作出猜测并同时公布,上帝随后揭晓答案,只有 Alice 和 Bob 都猜对才算这一轮胜利,否则就失败。13 轮猜测依次进行,上一轮结束后 Alice 和 Bob 都能看见上帝的答案和对方的猜测,然后再开始下一轮。
猜硬币之前,上帝会告诉 Alice 所有 13 轮上帝手握硬币的正反,也就是说 Alice 知道上帝每一轮出正面还是反面,但 Bob 不知道这些信息。
在上帝告诉 Alice 这些信息之前,Alice 和 Bob 可以互相交流制定策略(当然二人完全知悉以上所有规则,包括上帝告密的事情),但在上帝开始告密之后,双方便不能交流。
问:Alice 和 Bob 能否保证必胜 9 局?
(我们假设 Alice 和 Bob 被封闭于不同的两个房间内,只能通过一台显示终端做出猜测,并且不能不猜测。规定时间到后,机器同时公布两人猜测并验证答案是否正确,以保证双方绝对不能通过手势、口音、猜测时间等变量互相传递信息。双方只能通过自己的猜测给对方后续的猜测传递信息。)
若此题过于困难,可尝试简易版本:总共进行 9 轮猜硬币,保证必胜 6 局。

此题看似平平无奇,深入研究之后发现作者显然对此题的结构有深入研究,选取的数值非常巧妙,恰如其分。我们先从简易版的答案说起。


初探

初见此题,可能先会想到最简单的方法:奇数局提示偶数局的答案。Alice 在第奇数局猜下一局的正确答案,可保证下一局必然猜对。但这样保证猜对的局数不超过总局数的一半,显然是不够的。

利用分组的思想稍加变通,又可推出另一种稍强的策略:Alice 第 1 局提示第 2~4 局中占多数的正确答案(换言之,2~4 局的正确答案如果正面多,Alice 第 1 局就出正面,否则就出反面)。Bob 第 2~4 局每次都出 Alice 第 1 局猜的答案,Alice 在 Bob 猜对的那两局也出一样的答案,保证胜两局,剩下错的那局提示第 5~7 局中占多数的正确答案。如果不巧 2~4 局正确答案都相同,则约定 Alice 在第 4 局提示 5~7 局中的多数。此后依次类推。

可以看到这种策略把每 3 次猜测分成一组,每组可胜 2 局;剩下一局提示下一组的多数答案,保证可持续发展。这种策略可以保证 13 局胜 8 局,或者 9 局胜 5 局,但是还差一点。

下面转述来自智力题吧帖子(7楼)“毒酒滴冻鸭”大神的 9 局胜 6 局的方案:

首先 5 局可以保证胜 3 局:Alice 第 1 局提示 2~4 局多数答案。如果 2~4 局答案都一样则直接达成胜 3 局;否则 Alice 在错的那局提示第 5 局答案,拿下第 5 局,同样可以胜 3 局。
接下来给出 9 局胜 6 局的策略。
Alice 第 1 局提示 2~4 局多数答案,让 Bob 在 2~4 局每局都选这个答案。如果 2~4 局答案都一样,则双方 2~4 局全胜,后面只需执行 5 胜 3 的策略即可。
如果 2~4 局答案不都一样,则 Alice 在错的那局可以提示 Bob 一个答案,让 Bob 在 5~8 局每局都选这个答案。这里又分几种情况:
1)若 5~8 局正确答案全都一样或者成 3:1,则 Alice 提示 5~8 局的多数答案,而 Bob 在 5~8 局都猜这个答案。注意 2~4 局已经胜了 2 局,如果 5~8 局答案都一样则直接达成胜 6 局;否则 Alice 在错的那局提示第 9 局答案,拿下第 9 局,同样可以胜 6 局。
2)若 5~8 局答案为 PPQQ 形,则 Alice 在第 2~4 局中提示 P,然后 Alice 在第 5~6 局故意答错一次,无论在哪局答错,Bob 在第 7~8 局都改猜 P 的另一面,从而在 5~8 局中获胜 3 局。同时 Alice 通过选择答错第 5 局还是第 6 局告诉 Bob 第 9 局的答案,拿下第 9 局,目标达成。
3)若 5~8 局答案为 PQQP 形,则 Alice 在第 2~4 局本该获胜的两局中故意答错一次。Alice 用 2~4 局中本该答错的那局告诉 Bob 哪一面是 P,再通过选择答错两局中前一局还是后一局告诉 Bob 第 9 局的答案,于是能保证 5~9 局全胜,目标达成。
4)若 5~8 局答案为 PQPQ 形,则 Alice 在第 1 局故意告诉 2~4 局中占少数的那一面。这样 2~4 局中必然答错两局,Alice 在前一局告诉 Bob 哪一面是 P,后一局告诉 Bob 第 9 局的答案,于是能保证 5~9 局全胜,目标达成。

13 局胜 9 局的策略同样可以通过精心安排“故意错某些题传递特定信息”的方法构造,但符合要求的策略非常繁琐;另外,构造策略可以证明 13 局能胜 9 局,却不能证明 13 局不能保证胜 10 局,直接枚举所有策略又明显不可行。我们需要把上帝硬币问题转化为更简单的问题。


转换

首先规定:分别用 0,1 表示硬币的正面和反面。

转化问题的关键是利用最优子结构。Alice 每局猜测无非是为了两个目的:在这一局获胜,以及向 Bob 传递信息。设总共猜 n 局硬币,分成前 k 局和后 n-k 局两部分。现在只考虑 Alice 在前 k 局的行动,而把 Bob 的策略函数以及上帝前 k 局的正确答案看作是固定的,这样 Alice 有 2^k 种选择,每一种选择都对应一个结果:前 k 局中获胜了多少局。

姑且举一个最简单的例子:取 k=2,设 Bob 的策略函数是“第一局猜 0,第二局猜 Alice 第一局猜的结果”,上帝前 2 局的正确答案是 10。此时 Alice 在前 2 局有 4 种选择:00, 01, 10, 11,而 Alice 只有选 00 才能胜 1 局,其他三种选择都是一局不胜。若 Alice 选择一局不胜,那么 Alice 有 3 种等价的选择,相当于 Alice 此时可以向 Bob 传递一个范围为 1~3 的整数!整理一下就是:

  • Alice 可以选择胜 1 局,不传递额外信息;
  • Alice 也可以选择一局不胜,额外传递一个范围为 1~3 的整数。

现在假设我们要在 9 局中胜 6 局,前 2 局的情况如同以上假设的那样,则后 7 局就变成了下面的问题:

  • Alice 可以提前看到后 7 局的答案;
  • 看到答案后,Alice 可以选择喊出“我们要在 7 局中胜 5 局”(相当于 Alice 前 2 局选 00);
  • Alice 也可以选择喊出“我们要在 7 局中胜 6 局”,同时告诉 Bob 一个 1~3 的整数(相当于 Alice 前 2 局选 01, 10 或 11)。

这样我们把上帝硬币问题一般化,允许 Alice 在事先规定的范围内选择要胜的局数,并告诉 Bob 一个限定范围的整数。我们用一个简练的记号表示这种问题:例如,用 \langle 5,6^3\rangle 或者 \langle 5,6,6,6\rangle 表示“Alice 可以选择胜 5 局,或者选择胜 6 局并告诉 Bob 一个 1~3 的整数”。后面我们经常会把 \langle 5,6^3\rangle 这种记号看成一个多重集合:集合中有 1 个 5 和 3 个 6。

这里有一个小细节,当讨论问题 \langle 5,6^3\rangle 时,我们要规定 Alice 的 4 种选择都必须有可能出现。比如说,如果在任何情况下 Alice 都不报出“胜 6 局,数字为 1”,就视为违规。后面再解释这种奇怪规定的原因。

接下来我们马上会看到,这种问题是有最优子结构的!仍然以 \langle 5,6^3\rangle 举例(暂时不考虑总局数的条件,总局数未必是 7 局),下一局 Bob 面临 4 种情况:

  • Alice 喊出了“我们要胜 5 局”;
  • Alice 喊出了“我们要胜 6 局”并报出数字 1;
  • Alice 喊出了“我们要胜 6 局”并报出数字 2;
  • Alice 喊出了“我们要胜 6 局”并报出数字 3。

此外 Bob 再不知晓任何信息,因此 Bob 只能对每种情况指定一个 0/1 整数作为自己的猜测。先考虑第一种情况,假设 Bob 猜 0,那么在本局结束后又有 4 种分支:

  • 上帝的正确答案是 0,Alice 选了 0;
  • 上帝的正确答案是 0,Alice 选了 1;
  • 上帝的正确答案是 1,Alice 选了 0;
  • 上帝的正确答案是 1,Alice 选了 1。

如果是第一个分支,那 Alice 和 Bob 后面只需胜 4 局,否则就需要胜 5 局。请注意,我们在任何时刻总是把 Bob 的策略函数以及上帝已经揭示的正确答案看作是固定的,前者当然没有问题,我们没有更改 Bob 的策略,但后者要求我们把前两种分支(上帝的正确答案是 0 )和后两种分支(上帝的正确答案是 1 )分开处理。于是目前的状态不能记为 \langle 4,5,5,5\rangle,而是要记为 \langle 4,5\mid 5,5\rangle,竖线左边表示上帝本局选 0,右边表示上帝本局选 1。

另外还有一件非常重要的事:这 4 种分支都会出现吗?当然不一定!事实上 Alice 可以随意控制每一种分支是否出现。例如:

  • Alice 选择“当上帝本局正确答案是 0 时只猜 0”,就能禁掉第二种分支,将结果变为 \langle 4\mid 5,5\rangle
  • Alice 选择“只在上帝本局正确答案是 0 时才喊出‘我们要胜 5 局’”,则可直接禁掉后两种分支,结果变为 \langle 4,5\mid\ \rangle。至于如果上帝出 1 怎么办,当然是喊出“我们要胜 6 局”并报出一个数字了,这属于另外的情况,我们等会再说;
  • Alice 选择“只在上帝本局正确答案是 0 时才喊出‘我们要胜 5 局’,并且本局只猜 0”,则可直接禁掉后三种分支,结果变为 \langle 4\mid\ \rangle
  • ……

此处只有唯一一条限制:4 种分支至少要出现 1 种,否则 Alice 喊出“我们要胜 5 局”的情况就无法继续下去了。

最后,以上都是讨论 Bob 猜 0 的情况,事实上 Bob 还可以猜 1,此时仍然有 4 种分支,而本局结束后的状态则变为 \langle 5,5\mid 4,5\rangle。当然,Alice 仍然可以随意控制每一种分支是否出现。一般地,正整数 k 可以分裂为 \langle k-1,k\mid k,k\rangle\langle k,k\mid k-1,k\rangle 的非空“子集”。作为特殊情况,0 可以分裂为 \langle 0,0\mid 0,0\rangle 的非空“子集”,因为若要求 0 胜就根本不需要累加胜局了。

现在我们考虑 \langle 5,6^3\rangle 的每一种情况,每种情况都分裂成 1~4 个分支,例如考虑分裂

  • 5 分裂为 \langle 4,5\mid 5,5\rangle
  • 6 分裂为 \langle 5\mid\ \rangle
  • 6 分裂为 \langle 6,6\mid 5,6\rangle
  • 6 分裂为 \langle 6,6\mid 5,6\rangle

注意,竖线左边表示上帝本局选 0,右边表示上帝本局选 1,因此当我们把所有情况加总在一起后,结果便是

  • \langle 5,6^3\rangle 分裂为 \langle 4,5^2,6^4\mid 5^4,6^2\rangle

回忆一下,上帝前 2 轮给的答案是 10,于是结果就变成

  • 若上帝前 3 轮给的答案是 100,则前 3 轮过后问题变为 \langle 4,5^2,6^4\rangle
  • 若上帝前 3 轮给的答案是 101,则前 3 轮过后问题变为 \langle 5^4,6^2\rangle

只要问题 \langle 4,5^2,6^4\rangle 以及 \langle 5^4,6^2\rangle 都能在 6 局以内达成,\langle 5,6^3\rangle 就能在 7 局以内达成。要想验证 \langle 5,6^3\rangle 能否在 7 局以内达成,只需枚举所有可能的分裂,若存在一种分裂得到的两个多重集都能在 6 局以内解决,则 \langle 5,6^3\rangle 就能在 7 局以内达成,否则就不能。于是,这个问题确实是有子结构的!我们可以用动态规划的方法解决这个问题。对于原始问题,例如要判断 9 局胜 6 局是否可行,只要验证 \langle 6\rangle 能否在 9 局以内达成即可。

当然,分裂过程需要满足一些限定条件。具体地说,只需满足以下两个条件就可以了:

  • 每个数字分裂后不能是空集,例如 5 不能分裂为 \langle\ \mid\ \rangle,这个之前说过了;
  • 至少有一个数字分裂后竖线左边非空,并且至少有一个数字分裂后竖线右边非空。例如 5 可以分裂为 \langle 4\mid\ \rangle,6 可以分裂为 \langle 5\mid\ \rangle,但 \langle 5, 6\rangle 作为一个整体分裂为 \langle 4,5\mid\ \rangle 是不合法的。

此处可以说明之前奇怪规定的原因了,如果不做那种奇怪规定,当所有数字都分裂成左右两集时,有可能左边右边都有分支,但右边的所有分支都不可能出现,这是不可能做到的,因此干脆规定所有(没被显式禁掉的)分支都必须出现,以排除掉这种“隐形违规”的情况。

注意到,实际上只要补充定义“空的多重集 \langle\ \rangle 无论给多少局猜数字都不能解”,就可以自然排除掉第二个条件,以后就不用管第二个条件了。


优化

枚举所有可能的分裂比直接枚举策略快得多,但是还不够快。下面常用 M 表示由一些非负整数组成的多重集,用 M\in S_n 表示 M 可在 n 局内解决(此时也称 Mn 阶可解集)。

命题1M\in S_n,则 0<|M|\le 2^nM 中元素都不大于 n

前面解释过为什么 M 必须非空。前半句的后一个等号是因为我们要保证 M 中每种选择都可能出现,而上帝的答案一共就只有 2^n 种可能。后半句是显然的,Alice 总不能报出“我们要在 3 局中胜 5 局”吧。

我们把满足 0<|M|\le 2^nM 中元素都不大于 n 的多重集 M 称为“n 阶正常集”。

命题2 M\in S_0 当且仅当 M=\langle 0\rangle

由命题 1 直接推出。

命题3 若正常集 M 满足 |M|=2^n,则 M\in S_n

n=0 时命题显然成立,因为此时唯一一个正常集就是 \langle 0\rangle

对正整数 n,假设命题对 n-1 成立,我们让 M 的其中一半元素做分裂 x\rightarrow\langle x-1\mid\ \rangle(在做分裂操作时我们约定 0-1=0,否则每次都要对 0 特殊处理,写起来非常麻烦),另一半元素做 x\rightarrow\langle\ \mid x-1\rangle,这样左集和右集都是大小为 2^{n-1}n-1 阶正常集,由归纳假设知这两个集合都属于 S_{n-1},故 M\in S_n,即命题对 n 成立。归纳法证明完成。

(该命题从直观上非常容易理解:若 Alice 有 2^n 种喊话的选择,她完全告诉 Bob 所有正确答案保证 n 局全胜。)

命题4M_1\subseteq M_2 满足 M_1\in S_nM_2n 阶正常集,则 M_2\in S_n

简而言之就是“子集可解的正常集也可解”。n=0 时命题显然成立。

对正整数 n,假设命题对 n-1 成立,由于 M_1\in S_n,可设 M_1 分裂为 P,Q\in S_{n-1}。下面我们依次考虑 M_2-M_1 的元素如何分裂。记当前考虑的元素是 x\in M_2-M_1,分情况讨论:

  • 若当前 |P|<2^{n-1},则让 x 分裂为 \langle x-1\mid\ \rangle,并将 x-1 加入集合 P 中;
  • 若当前 |Q|<2^{n-1},则让 x 分裂为 \langle\ \mid  x-1\rangle,并将 x-1 加入集合 Q 中;(以上两条都满足时选第一条)
  • 若当前 |P|=|Q|=2^{n-1},注意到目前已经分裂完成的元素个数小于 2^n,于是必有元素分裂成不止一个分支,此时随便删去一个分支,再让 x 分裂为 \langle x-1\mid\ \rangle\langle\ \mid  x-1\rangle,取决于删掉的分支在左边还是右边。这样操作后仍有 |P|=|Q|=2^{n-1}

注意到只要中间有一步落入第三种情况,|P|=|Q|=2^{n-1} 的关系就会一直保持,直到最终 M_2-M_1 的所有元素都分裂完成时仍有 |P|=|Q|=2^{n-1},由命题 3 立刻可知 P,Q 仍属于 S_{n-1};否则,全过程始终没有落在第三种情况,则最终的 P,Q 分别以最初的 P,Q 为子集,根据归纳假设,此时 P,Q 仍属于 S_{n-1}。总之,最终 P,Q\in S_{n-1},从而 M_2\in S_n。这就完成了归纳递推的步骤。

实际上,|M|\le 2^n 的约束条件并没有什么重要意义,反倒给我们的推导过程制造了很多麻烦,于是有必要将可解集的概念作推广。

定义Mn 阶广义可解集,当且仅当 M\in S_n,或者 |M|>2^nM 中元素都不大于 n;称 Mn 阶广义正常集,当且仅当 M 非空且 M 中元素都不大于 nn 阶广义可解集的集合记为 \overline{S}_n

命题5M_1\subseteq M_2 满足 M_1\in\overline{S}_nM_2n 阶广义正常集,则 M_2\in\overline{S}_n

(该命题是显然的。)

命题6n 是正整数,则 M\in\overline{S}_n 当且仅当 M 能分裂为两个多重集 P,Q\in \overline{S}_{n-1}

必要性很容易证明。假设 M\in\overline{S}_n,若|M|\le 2^n,则 M 能分裂为两个集合 P,Q\in S_{n-1},自然满足条件;若 |M|>2^n,则 M 显然能分裂为两个大小不小于 2^{n-1} 的集合 P,Q,也满足条件。

下面证明充分性,假设 M 能分裂为两个多重集 P,Q\in \overline{S}_{n-1}。不妨设 |M|\le 2^n(否则结论自然成立),若 |P|,|Q|\le 2^{n-1},则 P,Q\in S_{n-1},结论自然成立。当然,|P|,|Q| 不能都大于 2^{n-1},故不妨设 |P|>2^{n-1},|Q|\le 2^{n-1}

此时,我们可以删掉一些落在左边的分支,使得 |P|=2^{n-1}。这个过程中也许 M 中某些元素的所有分支都删没了,这样的话就干脆把这个元素本身从 M 中移除。最终的结果就是 M 的某个子集分裂为多重集 P,Q,由 |P|=2^{n-1} 说明 P 可解,Q 从来没变过当然仍然可解,这就说明了 P,Q\in S_{n-1},从而 M 的某个子集可解,故 M 可解。证明完成。

现在我们终于摆脱了烦人的 |M|\le 2^n 的条件,姑且将结论叙述如下:

  • 给定一个非负整数的多重集,若集中任意元素均小于等于 n,且有子集属于 \overline{S}_n,则该集合本身也属于 \overline{S}_n
  • n 是正整数,则 M\in\overline{S}_n 当且仅当 M 能分裂为两个多重集 P,Q\in \overline{S}_{n-1}
  • M\in\overline{S}_0 当且仅当 M=\{0^k\},其中 k 是正整数。

至此终于可以推出我们想要的核心结论:

定义Mn 阶正常集,n 是正整数。若在某次分裂过程中,M 中所有小于 n 的数 x 都分裂为 \langle x-1,x\mid x,x\rangle 或者 \langle x,x\mid x-1,x\rangle,而所有数字 n 都分裂为 \langle n-1\mid\ \rangle 或者 \langle\ \mid n-1\rangle,则称此次分裂为 n 阶满分裂

命题7n 是正整数,则 M\in\overline{S}_n 当且仅当 M满分裂为两个多重集 P,Q\in \overline{S}_{n-1}

由命题 6 立即可得充分性。为证必要性,设 M 分裂为两个多重集 P,Q\in \overline{S}_{n-1},显然所有数字 n 都只能分裂为 \langle n-1\mid\ \rangle 或者 \langle\ \mid n-1\rangle。对于小于 n 的数字无论如何分裂,我们都把它补满为 4 个分支,由命题 5 可知如此操作过后仍有 P,Q\in \overline{S}_{n-1},于是就得到了满足要求的满分裂。

结论:若 n 是正整数,要判断是否有 M\in\overline{S}_n,只要枚举所有满分裂 P,Q,看能否让这两个多重集都属于 \overline{S}_{n-1} 就可以了。对于大小不超过 2^n 的集合,判断是否可解跟判断是否广义可解是一回事。

枚举满分裂比枚举所有分裂简单得多,因为每个数字都只需要考虑两种分裂方式。


实现

现在我们来看看前几个 n 对应的(广义)可解集是怎么样的。注意,由于包含可解集的集合也是可解集,故我们只需要枚举所有极小可解集就足够了。

n=0:可解集只有 \langle 0\rangle

n=1:极小可解集有 \langle 0\rangle,\langle 1^2\rangle

n=2:极小可解集有 \langle 0\rangle,\langle 1\rangle,\langle 2^4\rangle

n=3:极小可解集有 \langle 0\rangle,\langle 1\rangle,\langle 2^2\rangle,\langle 2,3^2\rangle,\langle 3^8\rangle

n=4:极小可解集有 \langle 0\rangle,\langle 1\rangle,\langle 2\rangle,\langle 3^2\rangle,\langle 3,4^7\rangle,\langle 4^{16}\rangle

……

随着 n 的增大,极小可解集的数量不断增加,需要编程枚举。为了方便计算,我们定义一个函数 t_n(M)(其中 M 是不含 n 的多重集),表示集合 M 中至少添加多少个 n 才能变成(广义)可解集:例如 \langle 3,4^7\rangle 是 4 阶极小可解集,故 t_4(\langle 3\rangle)=7。另外,用 f_n 表示 n 局游戏最多能保证猜对多少局。

容易看出,对任意 n,函数 t_n 仅在有限个多重集上取非 0 函数值,因此我们可以把 t_n 的自变量和对应非 0 函数值存进字典中。具体计算 t_n 要用到递推法:

假设已经算出 t_{n-1}。首先需要知道给定 M 如何算出 t_n(M)。任取 M 的一个满分裂,分裂得到的左右集可能含有 n-1,我们把这个分裂记为 M\rightarrow\langle M_1,(n-1)^r\mid M_2,(n-1)^s\rangle(也就是把 n-1 单拿出来)。查之前算的表可以获得 p=t_{n-1}(M_1),q=t_{n-1}(M_2) 的值,于是左集还差 \max(p-r,0)n-1,右集还差 \max(q-s,0)n-1。而每往 M 中添加一个 n,就可以(且只能)多分裂出一个 n-1。于是

t_n(M)=\min(\max(p-r,0)+\max(q-s,0)),

其中最外层的 \min 含义是遍历所有满分裂,取括号里的最小值。要遍历所有满分裂,设

M=\langle 0^{r_0},1^{r_1},\cdots,(n-1)^{r_{n-1}}\rangle,

枚举满足 0\le s_i\le r_i 的向量 (s_0,\cdots,s_{n-1}),让 r_ii 中的 s_i 个分裂为 \langle i-1,i\mid i,i\rangle,其余的分裂为 \langle i,i\mid i-1,i\rangle,就可以了。

然后考虑如何算出整个字典 t_n,也就是要枚举满足 t_n(M)>0M。还是设

M=\langle 0^{r_0},1^{r_1},\cdots,(n-1)^{r_{n-1}}\rangle,

按照 (r_0,\cdots,r_{n-1}) 的字典序枚举 M:从全 0 向量开始枚举,若当前 M 的函数值大于 0,则让 r_{n-1} 自增 1 得到下一个 M;否则,设 r_i 是最后一个非零项,显然再让 r_i 及以后的项往上增加没有意义,此时把 r_i 清零并让 r_{i-1} 自增 1。枚举过程中把函数值大于 0 的 M 以及其函数值放进字典中。最终,当我们枚举到某个单元素集 M 的函数值为 0 时,就没必要继续枚举了,此时终止枚举,而 M 中包含的唯一元素就是 f_n 的值。

由于我们计算 t_n 只是辅助,最终需要的还是 f_n 的值,于是就有了一个很方便的优化:假设我们需要计算 f_0,\cdots,f_N 的值,注意到 f_n 的值就是满足 t_n(\langle m\rangle)=0 的最大 m 值,即只需要考虑单元素集的 t_n 值;另外,任意集合分裂为左右两集,两集合各自的大小都不超过原集的两倍,从而只需要考虑不超过 2^{n-k} 元素之集的 t_k 值。于是就有:

计算 t_k 时若枚举到超过 2^{N-k} 个元素的集合,则套用 t_k(M)=0 的处理方式(即若 r_i 是最后一个非零项,则把 r_i 清零并让 r_{i-1} 自增 1),跳过这个集合。

这样当 k 接近 N 时可以大大缩短计算 t_k 的时间和空间。

利用以上方法,我用 Python 编写了一个程序,算出前几个 f_n 值如下:

\begin{array}{ccccccccccccc} n & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 & 11 & 12 \\ f_n & 0 & 1 & 1 & 2 & 3 & 3 & 4 & 5 & 6 & 6 & 7 & 8 \\ \\ n & 13 & 14 & 15 & 16 & 17 & 18 & 19 & 20 & 21 & 22 & 23 & 24 \\ f_n & 9 & 9 & 10 & 11 & 12 & 13 & 13 & 14 & 15 & 16 & 17 & 17 \\ \end{array}

大多数情况下 n 增加 1 时 f_n 也增加 1,少数情况下 n 增加 1 时 f_n 不变(显然这两种情况非此即彼,要么不变要么增加 1)。当 f_n=f_{n+1} 时,对应“n 局胜 f_n 局”的难度达到局部的“顶峰”,姑且将这些值单独整理成表格:

\begin{array}{ccccccc} n & 2 & 5 & 9 & 13 & 18 & 23 \\ f_n & 1 & 3 & 6 & 9 & 13 & 17 \\ \end{array}

可以看到,原题选取 9 胜 6 和 13 胜 9 两道题目,显然是已经对上帝硬币问题有了深刻的理解!


证明

最后补充一个严格证明,证明上帝硬币问题与多重集分裂问题是等价的。定义:

  • M\in S_0 当且仅当 M=\langle 0\rangle
  • M\in S_n(n\ge 1) 当且仅当 M 能分裂为两个集合 P,Q\in S_{n-1}

定义推广的猜硬币游戏:

  • 猜硬币总共进行 n 局。
  • 游戏开始前上帝告诉 Alice 和 Bob 一个多重集 MM 中元素均为不超过 n 的非负整数),然后 Alice 和 Bob 可以商量一个策略。
  • 商量好策略后分开二人,将所有正确答案告诉 Alice 一人,然后 Alice 可以在 M 中选一个整数报给 Bob,注意此时需要把 M 中相同数字打上不同的标签视为不同数字,例如若 M 中有 3 个 6,则可以附加一个 1~3 的整数标签,指明选的是哪个 6(可以类比为在黑桃 6、红桃 6、梅花 6 里选一张牌)。
  • 此后依次进行 n 局猜硬币,流程与原始问题一样。
  • 最终若赢的局数不低于 Alice 报出的数,就算 Alice 和 Bob 胜利,否则失败。
  • 本游戏有附加条件:要求两人的策略是确定性的,并且对 M 中每个元素都存在一个长为 n 的 01 串,使得若上帝的正确答案是这个 01 串则 Alice 会报出这个元素。

定理 Alice 和 Bob 能保证胜利,当且仅当 M\in S_n

证明:n=0 时命题显然成立,下面假设命题对 n-1 成立,证明命题对 n 成立。

先假设 Alice 和 Bob 存在一种策略能保证胜利。假设 Alice 报出的数字是 x,不妨设 Bob 此时第一轮猜 0,则有 4 种分支:

  • 上帝的正确答案是 0,Alice 选了 0;
  • 上帝的正确答案是 0,Alice 选了 1;
  • 上帝的正确答案是 1,Alice 选了 0;
  • 上帝的正确答案是 1,Alice 选了 1。

这些分支至少出现一个。如果出现第一个分支,就在左边放一个数字 x-1;如果出现后三个分支,就在左边(第二分支)或右边(第三、四分支)放一个数字 x。最终把左边所有数组成多重集 P,右边所有数组成多重集 Q。这与之前的分裂过程一致。

现在断言:若用多重集 P 进行 n-1 轮猜硬币游戏,则有必胜策略。

假设这 n-1 轮的正确答案是 s(它是长为 n-1 的 01 串),此时两人虚构一个在多重集 M 上进行的 n 轮猜硬币游戏,而正确答案是 0s,并套用已有的必胜策略,于是 Alice 选择报出一个数字 x,并在第一轮选了 0 或 1。若选 0,则 Alice 在现实中的 n-1 轮游戏中报出 x 分裂到左边的数字 x-1;若选 1,则 Alice 在现实中报出 x 分裂到左边的数字 x。而 Bob 在听到数字 x 后选择猜 0。

这时,在虚构游戏中 Bob 已经知道 Alice 报的数字以及 Alice 第一轮的选择,以后双方模仿已有的必胜策略即可。最终,双方在虚构的游戏中至少胜 x 局,于是在现实的游戏中至少胜 x-1x 局(取决于选了哪种分支),从而获得胜利。

同理可得:若用多重集 Q 进行 n-1 轮猜硬币游戏,则有必胜策略。由归纳假设, P,Q 都属于 S_{n-1},于是 M\in S_n,证明完成。

反过来,假设 M\in S_n,下面我们构造一个必胜策略。

由定义,可设 M 分裂为 M_0,M_1\in S_{n-1},然后再将 M_0,M_1 分裂为 M_{00},M_{01}\in S_{n-2}M_{10},M_{11}\in S_{n-2}。重复这个过程,直到得到 2^n 个属于 S_0 的集合为止,自然这些集合都是 \langle 0\rangle

现在将分裂过程中得到的所有集合中的所有元素都视为图的顶点,并在这些顶点之间连有向边,连边方法如下:

  • 若元素 x 分裂为 \langle x-1,x\mid x,x\rangle,则以原来的 x 为起点分别向 \langle x-1,x\mid x,x\rangle 中的 4 个元素连边,并且将 4 条边分别标记为 000, 010, 100, 110(如果 4 个元素有些没有出现,就不连那条边);
  • 若元素 x 分裂为 \langle x,x\mid x-1,x\rangle,则以原来的 x 为起点分别向 \langle x,x\mid x-1,x\rangle 中的 4 个元素连边,并且将 4 条边分别标记为 011, 001, 111, 101(如果 4 个元素有些没有出现,就不连那条边)。

(标记 xyz 的含义为:本轮上帝选 x,Alice 选 y,Bob 选 z。)

如此便构成了一个多叉森林,根节点是 M 中所有元素,叶子节点是每个 M_ss 是长为 n 的 01 串)中唯一一个元素 0。

Alice 和 Bob 事先约定并记住这个多叉森林。假设上帝正确答案是长为 n 的 01 串 s,Alice 首先找到 M_s 中唯一元素并向前找路,直到找到 M 中某个元素 x 为止(显然 M 中仅有唯一元素可以通向 M_s,且通路唯一),然后报出这个元素。此后 Alice 和 Bob 按照这条路上的标记去猜硬币,沿这条路行进的过程中数字至少自减了 x 次,而只有走过标有 000 或 111 的边,数字才会减小 1,否则不变,走过这些边相当于赢了一局,于是总共至少赢了 x 局,并且最终会走到 M_s 中唯一元素,这个过程中上帝公布的正确答案序列就是 s 没有问题。

Bob 的策略是唯一确定的,这是因为每次猜硬币过后无论 Alice 还是 Bob 都很清楚当前走到了哪个节点,而每个节点所有出边的标记的最后一位要么都是 0,要么都是 1,这样 Bob 就能确定猜哪个了;而 Alice 事先知道走哪条路,只需选择对应的数字即可。因此该策略的确是成立的必胜策略。


后记

本文给出了一种判定上帝硬币问题是否可解的算法(事实上,如果可解,本文最后一节还给出了构造必胜策略的方法),顺带解决了推广的上帝硬币问题。

上帝硬币问题仍有一些问题值得研究,最基础的问题便是能否给出 f_n 的显式表达式。如果不能,至少要问 f_n/nn 趋于无穷的极限值是多少。

另外,除了单调性以外,函数 t_n 也许满足一些不太显然的性质,可以利用这些性质优化算法。之前我曾根据 n 取较小值的一些结果,认为函数 t_n 满足某种凸性,即

t_n(\langle M,(n-1)^{r-1}\rangle)+t_n(\langle M,(n-1)^{r+1}\rangle)\ge 2t_n(\langle M,(n-1)^r\rangle),

若规律成立,则可能用三分法等算法加速。但很遗憾,这是错的。第一个反例出现在 n=17 时,计算可得

t_{17}(\langle 13,15^{45},16^{71}\rangle)=5048, \\ t_{17}(\langle 13,15^{45},16^{72}\rangle)=5003, \\ t_{17}(\langle 13,15^{45},16^{73}\rangle)=4957,

它不满足上述不等式。

编辑于 08-19