新学期社团招新,学生会主席收到三张签到表:算法社签到 40 人、篮球社签到 30 人、辩论社签到 25 人。他要向学校汇报"至少参加了一个社团的总人数"。
他顺手一加:40 + 30 + 25 = 95 人。结果辅导老师一看就摇头:"你们学校一共才 80 个学生,怎么可能 95 人?"
问题出在重复计数:同时报了两个社的同学被数了两遍。设算法∩篮球有 10 人、算法∩辩论有 8 人、篮球∩辩论有 6 人,把这三块减掉后得到 95 − 10 − 8 − 6 = 71 人。
但还没完!同时报了三个社的同学(比如 3 人),在前面的运算中被"加了三次、减了三次",最后净贡献是 0 —— 他们被漏掉了!所以要再加回来一次:71 + 3 = 74 人。
这就是容斥原理(Inclusion–Exclusion Principle):先无脑加,再减掉两两重复的,再加回三三重复的,减掉四四重复的…… 符号一正一负交替,直到全部修正完毕。
故事里还藏着一个几乎无关的第二幕:如果报到顺序有约束 —— 比如"每个时刻算法社的报名人数都不少于篮球社",那么合法的流程有多少种?答案会被压缩到一串神奇的数字:1, 1, 2, 5, 14, 42, 132… 这就是卡特兰数。
💡 故事背后的算法思想
容斥原理解决"并集的规模"。凡是问题里出现"至少满足一个""都不满足""恰好满足 k 个",本质上都在问并集或并集的补集。它的核心动作只有两个:枚举所有子集 + 按子集大小交替定符号。
卡特兰数是容斥原理的一个著名推论。"不越过对角线的格路数 = 总路径数 − 越线路径数",而越线路径数恰好可以用反转法(反射原理)一一对应到另一类无约束路径。于是 Catn = C(2n,n) − C(2n,n+1) = C(2n,n)/(n+1)。
一句话总结:容斥负责"减去不合法",卡特兰负责"数出合法的"。