#013. 经典脑题 III:毒酒、四和、帽子与信封

先用一个小例走通

两名检测者各给“阳/阴”两种结果,一次并行检测最多出现00、01、10、11四种图案,即两比特信息;要区分5种候选就不够。帽子题的“公共知识”则是所有人听到同一句话,而且知道别人也听到了;第二个人因此能把第一个人的“不知道”当作新约束,而非无信息的沉默。

脑筋急转弯板块知识地图:本章聚焦编码博弈一支的二进制编码与条件期望

#学习目标:信息怎么被编码、被传递、被误用

本章四道题排成一条「信息主线」。毒酒题问:一次实验最多能产出多少信息?答案是每人一比特,于是 100 种可能性最少需要 7 个人——这是信息论下界在面试里最朴素的样子。四和题问:无序的观测能不能反解出有序的未知数?答案可能不唯一;应枚举合法边对应、用方程恢复候选,再验证完整多重集合。帽子题问:「我不知道」这句话本身携带多少信息?答案是:当所有人都理性时,一句「不知道」能排除一整族可能世界,这正是公共知识(common knowledge)的力量。两信封题问:一段看起来无懈可击的期望计算为什么会导出荒谬结论?答案是它偷偷把「同一个数」用在了两个互斥的条件事件上——条件期望(conditional expectation)的适用边界必须搞清楚。

这四种能力在量化面试后续章节都会再出现:编码思想对应009 章位运算,反解未知数对应026 章回归,公共知识对应024 章博弈论,条件期望的正确姿势对应020 章与028 章。本章各取其最小版本。

编码视角

n 个二元输出的观测者最多区分 \(2^{n}\) 种假设;想让区分能力最大,就要让每种假设对应一个唯一的输出组合——二进制编码。

反解视角

六个和齐全时可用最小/最大和定位;缺失一和时这些身份可能已缺失,应枚举完整三角形并验证多重集合,不能直接认领。

条件期望视角

对观测值 \(v\) 做条件期望时,两种互斥情形的权重是后验概率,不是想当然的各一半。

#知识点一:一次观测值多少比特

信息论的基本账本:一个只有「生/死」「是/否」两种结局的观测者,一次实验最多产出 1 比特信息。\(n\) 个这样的观测者一共能区分的世界数不超过:

\[ \#\text{可区分假设} \le 2^{n} \]

怎么读:\(n\) 个人的生死状态是一个 \(n\) 位 0-1 向量,总共 \(2^{n}\) 种;若要在这 \(2^{n}\) 种状态与「哪瓶酒有毒」之间建立一一对应,假设总数不能超过 \(2^{n}\)。反过来,只要假设数不超过 \(2^{n}\),总可以用二进制编码构造出一一对应——给每个假设写一个 \(n\) 位二进制编号,第 \(i\) 位观测者检验「编号的第 \(i\) 位是否为 1」。于是「最少几个人」这类问题的答案永远是:

\[ n_{\min} = \left\lceil \log_{2}(\#\text{假设}) \right\rceil \]

怎么读:人数是对「假设数的以 2 为底对数」向上取整。毒酒题里 \(\log_{2} 100 \approx 6.64\),向上取整得 7。这个「下界 + 构造」的两段式论证结构(先证少于 7 人不够,再给出 7 人的具体方案)适用于几乎所有编码类脑题,包括天平称球、一次提问猜数等变式。

为什么二进制编码是最优的

下界来自输出向量的计数:7 人只有 \(2^{7} = 128\) 种生死组合,6 人只有 64 种,装不下 100 瓶酒;构造来自二进制:每个 0-99 的数有唯一的 7 位二进制表示,把「酒号」映射到「死哪些人」,信息一分不损。上下界咬合,答案就是刚好的 7。

#知识点二:公共知识与条件期望的两把刀

第一把刀:把「不知道」当数据。帽子题里每个人能看见别人、看不见自己,唯一的交流是依次宣布「知不知道」。理性人说出「我不知道」,等于宣告:与我所见一致的所有可能世界里,我的颜色不唯一。听者拿到这句话,就能排除「若你是某颜色你就会知道」的那些世界。推理链每多一环,可能世界就瘦一圈。这类推理的严格名字是公共知识推理——「我知道你知道我不知道」逐层展开。024 章的博弈均衡分析用的也是同一层逻辑:策略推理的本质是对「别人怎么想」建模。

第二把刀:条件期望必须带上权重。设你打开信封看到金额 \(v\),另一封是 \(2v\) 还是 \(v/2\) 并非对半开,而由信封金额的先验分布决定。正确的条件期望是:

\[ \mathbb{E}[\text{另一封} \mid v] = 2v \cdot q(v) + \frac{v}{2}\bigl(1 - q(v)\bigr), \qquad q(v) = \Pr[\text{你拿的是小信封} \mid v] \]

怎么读:\(q(v)\)由金额生成先验与已见金额共同决定,不能从“随机拿一只”推出它恒等于1/2。例如小金额先验密度为f时,见v的两条未归一化密度权重为f(v)/2与f(v/2)/4,后者多一个变量变换因子;不是所谓“无界均匀先验”自动给对半后验。原题没有提供先验,所以打开后的最优动作不能仅凭对称性决定。两把刀都要求把观测、条件化与推断对象写清楚。

识别悖论题的信号

只要一个论证推出「无条件占优的策略」(换永远好、停永远好),就应该立刻怀疑:它多半在不同分支上用了不一致的概率假设。合法的无条件结论只能来自对称性(两信封互换不改变联合分布),而对称性给出的答案永远是「换与不换期望相同」。

#例题详解一:100 瓶毒酒与 7 位品酒师

例题 1:100 瓶酒中恰有一瓶有毒,毒发时间为一天。明晚有宴会,你需要在那之前确定毒酒。可以雇若干品酒师,每人可以试多瓶酒(混着喝没有问题,毒量足够)。最少雇多少人?

建模。一天的时间限制意味着只有一轮实验:所有品酒师今晚同时喝,明天看生死。每个人是一比特信道:活/死。要把「100 种毒酒假设」装进「\(n\) 人的生死组合」里,用知识点一的下界加构造框架。

推导。下界:\(n\) 个人的生死状态至多 \(2^{n}\) 种,要区分 100 瓶,需 \(2^{n} \ge 100\)。\(2^{6} = 64 \lt 100 \le 128 = 2^{7}\),故 \(n \ge 7\)。构造:把瓶子编号为 0 到 99,写成 7 位二进制 \(b_{6}b_{5}\dots b_{0}\)。第 \(i\) 位品酒师喝下所有第 \(i\) 位为 1 的酒(每人约喝 50 瓶的混合样)。次日,把 7 个人的状态排成一个 7 位向量:死了记 1、活着记 0——这个向量的二进制值恰好就是毒酒的编号。例如只有第 0 位和第 6 位品酒师死了,则毒酒编号是 \(1000001_{2} = 65\) 号。若无人死亡,编号是 0(全零向量),对应 0 号瓶——所以编号必须从 0 开始,恰好把 \(2^{7} = 128\) 个输出组合中的前 100 个用满。

检验。逐一核对:不同毒酒的二进制编号不同,死者的集合必不同,因此方案无歧义;每人一比特,7 比特 \(\ge \log_{2} 100 \approx 6.64\) 比特,信息量刚好够。边界情形:全活对应 0 号酒,全死对应 127 号——127 号不在 0 到 99 范围内,所以「全死」不会出现,输出集合与假设集合一一对应。时间约束也满足:只需一个昼夜。

面试怎么讲。先报答案「7 人」,再给两段论证:「64 种生死组合装不下 100 瓶,所以 6 人不够;7 人够,因为把瓶号写成 7 位二进制、让第 \(i\) 人喝所有第 \(i\) 位是 1 的酒,死者集合的二进制就是毒酒编号。」若扩展到多轮,死亡者不能再次参加。每人最多输出“第几轮死亡”或“全程存活”,r 轮、k 人最多提供 \((r+1)^k\) 种结果,不能按 \(2^{kr}\) 计数;例如 2 人、4 轮至多区分 25 瓶。构造时还须保证各轮取样与毒发时间可区分。

推导补全与自检。先给下界:6个人只有64种生死图案,分不清100瓶;7个人有128种,才可能。再把瓶号0…99写成7位二进制,第j人喝第j位为1的所有瓶;次日死亡位图就是毒瓶编号。编号0对应无人死亡,在“恰一瓶毒且毒必发”的假设下仍有意义;若还允许没有毒,则必须另留一种图案表示无毒,所需编码数改为101。

#例题详解二:四个正整数与五个两两和

例题 2(源题 B8):四个正整数的六个两两和缺一个,已知其余五个,如何恢复?

先检查是否唯一。PDF 未说明缺的是哪一个和,因此不能把五个已知和中最小的直接认成 a+b;真正的最小和可能正是缺失项。题目也未保证唯一解,应返回全部满足条件的有序后排序四元组,或报告无解/不唯一。

从完整三角形恢复三个数。把四个数看成四个顶点、两两和看成六条边。只缺一条边时,至少有一个三顶点三角形的三条边全在已知数据里。枚举三个不同的观测位置,假设其值分别为 \(u=a+b,v=a+c,w=b+c\),则 \(a=(u+v-w)/2\)、\(b=u-a\)、\(c=v-a\)。只保留正整数。第四个数 d 至少有一条与这三个数相连的已知边,枚举 \(d=s-a,s-b,s-c\),再把候选的六个和作为多重集合核对:五个观测必须能逐一删除,且恰剩一个和。

set<array<long long, 4>> recoverFour(const vector<long long>& sums) {
    if (sums.size() != 5) throw invalid_argument("need five sums");
    set<array<long long, 4>> answers;
    // Choose an intact triangle: u=a+b, v=a+c, w=b+c.
    for (int i = 0; i < 5; ++i) for (int j = 0; j < 5; ++j)
        for (int k = 0; k < 5; ++k) {
            if (i == j || i == k || j == k) continue;
            long long twiceA = sums[i] + sums[j] - sums[k];
            if (twiceA <= 0 || twiceA % 2) continue;
            long long a = twiceA / 2, b = sums[i] - a, c = sums[j] - a;
            if (b <= 0 || c <= 0) continue;
            for (long long sum : sums) for (long long x : {a, b, c}) {
                long long d = sum - x;
                if (d <= 0) continue;
                array<long long, 4> values{a, b, c, d};
                sort(values.begin(), values.end());
                multiset<long long> all;
                for (int p = 0; p < 4; ++p) for (int q = p + 1; q < 4; ++q)
                    all.insert(values[p] + values[q]);
                bool valid = true;
                for (long long known : sums) {
                    auto it = all.find(known);
                    if (it == all.end()) { valid = false; break; }
                    all.erase(it);  // Repeated sums consume separate copies.
                }
                if (valid) answers.insert(values);
            }
        }
    return answers;
}

例子与复杂度。对 \(\{3,5,6,10,12\}\),候选 \((1,2,4,8)\) 的六和为 \(\{3,5,6,9,10,12\}\),缺9。代码同时排查其他候选。由于观测恒为五个,枚举次数与整数数值大小无关;按固定宽度整数运算计为常数时间、结果集合空间为常数级。代码要求两两和及中间加减能放进 long long;更大输入须改任意精度。

推导补全与自检。不能用缺边后的顺序代替完整六和的顺序。例如四数(1,2,3,4)的六和为{3,4,5,5,6,7},缺3后,已知最小和4就不是最小两数之和。用多重集合验证还避免把两个相同数值的和错误合并成一条边。

#例题详解三:三蓝两红帽子

例题 3:房间里有三蓝两红五顶帽子,三人在黑暗中各戴一顶(自己看不见自己的)。走到亮处后,第一人看了后两人说「我不知道自己什么颜色」;第二人听了之后看了第三人,说「我也不知道」;第三人是盲人,听完后说「我知道我的颜色」。第三人戴什么颜色的帽子?

建模。只有两顶红帽。第一人的视野是第二、三人的帽子;他能确定自己颜色的唯一情形是看见两顶红(红帽只有两顶,全在别人头上,自己必蓝)。他说「不知道」,这句话对全世界广播了一条信息:第二、三人不同时戴红。第二人接收这条信息后仍只能看第三人:若第三人戴红,则由「不同时红」,第二人立刻推出自己必蓝;他说「不知道」,等于广播:第三人不是红。第三人是盲人,但两条广播加起来足以定案。

推导。把推理链形式化。记三人为 \(P_{1},P_{2},P_{3}\),帽色 \(c_i \in \{B, R\}\),红帽总数 2。第一句:\(P_{1}\) 不知道 \(\Rightarrow \neg(c_{2}=R \wedge c_{3}=R)\)。第二句:\(P_{2}\) 已知上式且看见 \(c_{3}\)。若 \(c_{3}=R\),则「二、三不同时红」迫使 \(c_{2}=B\),\(P_{2}\) 本可立刻自知为蓝;他仍说不知道,唯一可能是 \(c_{3}=R\) 这个情形本身不成立,故 \(c_{3} \ne R\)。结论:

\[ c_{3} = B \]

第三人戴蓝色帽子。

检验。例如第三人蓝、第二人红时,第一人看到红蓝,不知道自己颜色;第二人看到第三人蓝,结合第一句仍不能排除自己红或蓝,因此第二句也成立。若第三人红,则第一句排除第二人红,第二人本应知道自己蓝,与他说“不知道”矛盾。这只用到必要的可见信息,不需要第三人看任何帽子。

面试怎么讲。「盲人听到的是两条信息:第一句排除『二、三两人同时红』,第二句在这个基础上排除『第三人红』——所以第三人必蓝。」可以补一句推广:若有 \(k\) 顶红帽、\(k+1\) 个人依次说不知道,前 \(k\) 句「不知道」逐层把红帽往下挤,第 \(k+1\) 个发言者必能宣布自己蓝色——本题是 \(k=2\) 的最小版本,和「黑帽白帽连续不知道」是同一家族。

推导补全与自检。第一人不知道,排除“后两人都红”。第二人若看见第三人为红,就能由前句话推断自己非红而是蓝;但他说不知道,说明第三人不红,即蓝。注意第二句使用的是“第一人不知道”这一公开信息,第三人无需看见任何帽子。若有人可能不诚实或不具备共同推理能力,结论不再被保证。

#例题详解四:两信封问题

例题 4:两只信封装有 \(x\) 和 \(2x\)。你随机拿走一只,看到里面金额后,可以决定换或不换。换不换?

建模。先写对称性答案再解剖悖论。设你信封金额为 \(Y\),另一封为 \(Z\)。拿信封是完全对称的随机动作,\((Y, Z)\) 与 \((Z, Y)\) 同分布,因此 \(\mathbb{E}[Y] = \mathbb{E}[Z]\),换与不换的期望完全相同。再看著名的错误论证:设看到金额 \(v\),「另一封以一半概率是 \(2v\)、一半概率是 \(v/2\)」,于是:

\[ \tfrac{1}{2}(2v) + \tfrac{1}{2}\left(\tfrac{v}{2}\right) = 1.25\,v \gt v \]

照此推理永远该换——但「换完再看一次」又能推出该换回来,荒谬。

推导。错误出在那两个 \(1/2\):它们不是概率,而是被默认的先验。正确的条件期望要引入后验权重 \(q(v) = \Pr[\text{你拿的是小信封} \mid Y = v]\):

\[ \mathbb{E}[Z \mid Y=v] = 2v \cdot q(v) + \frac{v}{2}\bigl(1-q(v)\bigr) \]

该换的条件是它大于 \(v\),化简(\(v \gt 0\))得 \(3q(v) \gt 1\),即 仅当你拿小信封的后验概率超过 \(1/3\) 时才值得换。而 \(q(v)\) 由信封金额 \(x\) 的先验分布决定:在某些具体先验下,看到很大的 \(v\) 时 \(q(v)\) 偏小,不该换;看到很小的 \(v\) 时 \(q(v)\) 偏大,该换。要让错误论证成立需要 \(q(v) \equiv 1/2\) 对一切 \(v\) 成立,在常见密度模型下会要求尺度不变的非正规权重;它不能作为任意金额上的合法等概率后验假设——这样的概率分布不存在(测度无法归一)。所以「无条件该换」从来不是合法结论。

检验。总是交换与总是不交换,在打开前因对称而有相同期望;这不意味着“看过金额后再决定”的所有策略等价。若已知两封只有10和20,看见10就换、看见20就不换,最终恒得20,优于无条件策略的均值15。原题未给金额生成先验,因此不能从看到的金额独立算出 q(v)。期望比较还须假设有关期望存在。

面试怎么讲。分三层:「第一,对称性说明换不换期望相同;第二,1.25 倍论证的错在于把两种情形的后验权重想当然设为一半,这需要一个不存在的无界均匀先验;第三,正确的条件换法是:看到金额后估计自己拿小信封的后验概率,超过三分之一才换。」能讲到第三层(并且说出 \(1/3\) 这个阈值)的候选人极少,这是这道经典题的满分线。

推导补全与自检。设看见金额为 a。换后期望应写 P(原为较小|a)·2a+P(原为较大|a)·a/2,两个条件概率由生成金额的先验决定,通常不是各\(1/2\)。例金额只可能为 (10,20),看见10必换、看见20不换;未打开前交换对称无优势。“对任何a都同样可能较大/较小”不能由“随机拿一只”推出。

#误区与边界

四个高频翻车点

一,毒酒题答 100 人或 99 人(一人一瓶试):没有意识到「每人可试多瓶」把生死变成比特,混合样本不损失定位能力。二,四和题忘记分情形:直接假设 \(w_{3}\) 是 \(a+d\) 或直接假设是 \(b+c\),另一情形可能才是正整数解;也有人忘记编号从 0 开始导致毒酒题的「全活」输出对不上。三,帽子题跳步:直接说「第三人蓝」而说不出两句「不知道」各排除了什么,面试官会追问到链断裂为止。四,两信封题把「无条件换不换」与「看到金额后的最优策略」混为一谈:前者由对称性直接判等价,后者必须引入先验并算后验。

变式与追问

毒酒变式:三天时间、每天一批结果——「轮数×人数」提供总比特;或者毒酒不止一瓶,答案变成向上取整的对数除以编码每瓶所需比特。四和变式:给五个两两乘积(先取对数化为和)、或给四个和少一个约束(解不唯一时要能指出自由度)。帽子变式:人数增多、颜色增多、或允许沉默与眨眼(信息论里的信号通道)。信封变式:金额上限已知(先验有界,此时小额该换、大额不该换的直觉终于有了严格版本)。所有变式的共同考点:先问「这一步操作传递了多少信息」,再动笔。

#检查清单

  • 我能用「\(2^{n}\) 种生死组合」证明 100 瓶酒至少 7 人,并写出 7 人的二进制编码方案。
  • 我能解释为什么编号要从 0 开始:全零输出(无人死)必须对应一个真实假设。
  • 我能解释缺失一个和为何破坏排序身份认领,枚举完整三角形、恢复候选,并以多重集合核对所有观测。
  • 我会用正整数性与剩余等式筛选四和题的假解,并能指出数据退化时解不唯一。
  • 我能把帽子题的每一句「不知道」翻译成对可能世界的排除,并推出第三人必蓝。
  • 我能指出两信封悖论的病根:默认 \(q(v)=1/2\) 等价于不存在的无界均匀先验。
  • 我能推导换信封的阈值条件 \(3q(v) \gt 1\),并用对称性一票否决「永远该换」。
  • 我养成了动笔前先问「每个观测/每句话各值多少比特」的习惯。