通过多维集合维恩图的交叠面积重绘,演示奇加偶减的计数精髓
在计数时,为了求几个集合并集的大小,我们先将所有集合大小相加,然后减去多加的交集,再补回多扣的交集,以此类推。这种奇数个集合的交集相加,偶数个集合的交集相减的算法即为容斥原理。
设 $A_1, A_2, \ldots, A_n$ 为有限集合,它们的并集大小公式为:
二进制掩码实现:如果有 $n$ 个集合,我们可以用一个从 $1 \to 2^n-1$ 的二进制数掩码表示选择哪些集合求交集。若选择集合的个数为奇数,符号为正;若为偶数,符号为负。
// 容斥原理:求 [1, N] 内能被素数集合 primes 整除的数的个数
long long countDivisible(long long n, vector<long long> primes) {
long long ans = 0;
int k = primes.size();
// 二进制掩码:枚举所有 2^k - 1 个非空子集
for (int i = 1; i < (1 << k); i++) {
long long lcmVal = 1;
int cnt = 0; // 子集大小
for (int j = 0; j < k; j++) {
if ((i >> j) & 1) {
lcmVal = lcm(lcmVal, primes[j]);
cnt++;
}
}
// 容斥定理:奇数个集合加,偶数个集合减
if (cnt % 2 == 1) ans += n / lcmVal;
else ans -= n / lcmVal;
}
return ans;
}