容斥原理的证明


容斥原理的证明

原链接地址

容斥原理(翻译) - vici - C++博客

       我们要证明下面的等式:

       

         其中B代表全部Ai的集合

         我们需要证明在Ai集合中的任意元素,都由右边的算式被正好加上了一次(注意如果是不在Ai集合中的元素,是不会出现在右边的算式中的)。

         假设有一任意元素在kAi集合中(k>=1),我们来验证这个元素正好被加了一次:

         size(C)=1时,元素x被加了k次。

         size(C)=2时,元素x被减了C(2,k)次,因为在k个集合中选择2个,其中都包含x

         size(C)=3时,元素x被加了C(3,k)次。

         ……

         size(C)=k时,元素x被加/减了C(k,k)次,符号由sign(-1)^(k-1)决定。

         size(C)>k时,元素x不被考虑。

         然后我们来计算所有组合数的和。

         

         由二项式定理,我们可以将它变成

      

 

         我们把x取为1,这时表示1-T(其中Tx被加的总次数),所以,证明完毕。


(自己画的图示理解)


      题目

    能满足一定数目匹配的字符串的个数问题

       给出n个匹配串,它们长度相同,其中有一些’?’表示待匹配的字母。然后给出一个整数k,求能正好匹配k个匹配串的字符串的个数。更进一步,求至少匹配k个匹配串的字符串的个数。

         首先我们会发现,我们很容易找到能匹配所有匹配串的字符串。只需要对比所有匹配串,去在每一列中找出现的字母(或者这一列全是’?’,或者这一列出现了唯一的字母,否则这样的字符串就存在),最后所有字母组成的单词即为所求。

         现在我们来学习如何解决第一个问题:能正好匹配k个匹配串的字符串。

         我们在n个匹配串中选出k个,作为集合X,统计满足集合X中匹配的字符串数。求解这个问题时应用容斥原理,对X的所有超集进行运算,得到每个X集合的结果:

       

         此处f(Y)代表满足匹配集合Y的字符串数。

         如果我们将所有的ans(X)相加,就可以得到最终结果:

         

         这样,就得到了一个复杂度的解法。


         这个算法可以作一些改进,因为在求解ans(X)时有些Y集合是重复的。

         回到利用容斥原理公式可以发现,当选定一个Y时,所有 X的结果都是相同的,其符号都为。所以可以用如下公式求解:

         

         这样就得到了一个复杂度的解法。

         现在我们来求解第二个问题:能满足至少k个匹配的字符串有多少个。

         显然的,我们可以用问题一的方法来计算满足kn的所有结果。问题一的结论依然成立,不同之处在于这个问题中的X不是大小都为k的,而是>=k的所有集合。

         如此进行计算,最后将f(Y)作为另一个因子:将所有的ans做和,有点类似二项式展开:


在《具体数学》( Graham, Knuth, Patashnik. "Concrete Mathematics" [1998] )中,介绍了一个著名的关于二项式系数的公式:


根据这个公式,可以将前面的结果进行化简:


那么,对于这个问题,我们也得到了一个的解法:



### 容斥原理概述 容斥原理是一种用于计算多个集合并集大小的方法,在处理重叠情况时尤为有用。该方法通过加减不同集合及其交集中元素的数量来获得最终结果。 对于两个有限集合 \(A\) 和 \(B\), 并集的元素数量可以通过下面公式得出: \[ |A \cup B| = |A| + |B| - |A \cap B| \] 当扩展到更多集合时,比如三个集合\( A, B,\) 和 \(C\) ,则有更复杂的表达形式: \[ |A \cup B \cup C| = |A| + |B| + |C| - |A \cap B| - |A \cap C| - |B \cap C| + |A \cap B \cap C| \][^1] 这种模式遵循交替相加和相减的原则,随着涉及的集合数目增加而继续下去。 ### 应用实例分析 考虑一个具体例子有助于理解如何应用这一原则。假设要找出满足某些条件的人群总数——例如,“高富帅”,“高穷挫”,“矮富帅”。如果这些类别间存在交叉,则直接累加各组人数会重复计数那些属于多类别的个体。此时便需采用容斥原理调整统计方式[^4]。 设 `cnt[i]` 表示恰好具备 i 种属性的人数,则总人数可由下述关系给出: - 对于单个特征组合:`cnt[1]` - 减去两两配对的情况: `-2 * cnt[2]` - 加回三者皆有的情形: `+3 * cnt[3]` 如此这般能够精确算得实际符合条件者的整体规模而不至于遗漏或过量估算任何部分群体成员。 ### 推导过程中的不等式验证 在特定条件下,为了简化计算或者证明结论的有效性,可能需要用到一些辅助性的数学工具。例如,给定正整数 n 和 k 的情况下,若想表明某个关于它们之间的不等式的正确性,可以借助带余除法来进行逻辑演绎。即设定 \(n = pk + q\) (其中 p 是商,q 是小于 k 的非负余数),进而展示出所需的关系链路[^2]: ```python def verify_inequality(n, k): p = n // k # 整除运算获取商 q = n % k # 取模操作得到余数 return k > q and k*(p+1)>n ``` ### 集合枚举策略 面对复杂场景下的多重交集问题,一种有效的解决方案是运用位掩码技术(bitmasking)。这允许程序设计人员高效地标记哪些集合被选中参与当前考量范围之内,并据此动态更新累积值直至遍历完毕所有可能性为止[^3]。 #### Python 实现示意代码片段 ```python from itertools import combinations def inclusion_exclusion(set_sizes, intersection_counts): result = sum((-1)**len(subset)*intersection_counts[tuple(sorted(subset))] for r in range(len(set_sizes)+1) for subset in combinations(range(len(set_sizes)), r)) return abs(result) # 假设有四个集合 {S1,S2,S3,S4} sets_info = { (): 0, (0,): 10, (1,): 8, (2,): 7, (3,): 9, (0, 1): 5, (0, 2): 4, (0, 3): 6, (1, 2): 3, (1, 3): 4, (2, 3): 5, (0, 1, 2): 2, (0, 1, 3): 3, (0, 2, 3): 4, (1, 2, 3): 3, (0, 1, 2, 3): 1 } print(inclusion_exclusion([10, 8, 7, 9], sets_info)) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值