专栏文章

更通用的容斥原理

算法·理论参与者 7已保存评论 6

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
6 条
当前快照
1 份
快照标识符
@mjreomgr
此快照首次捕获于
2025/12/30 01:02
2 个月前
此快照最后确认于
2026/02/19 01:25
15 小时前
查看原文

更一般的的容斥原理

对于同一固定全集 UU 上的子集 A1,A2,,AnUA_1,A_2,\dots,A_n\subseteq U,令 f:P(U)Gf:\mathcal P(U)\to Gff 是一个函数,其定义域为 UU 的所有子集,值域为 GG), 其中 GG 为阿贝尔群(运算结果封闭于 GG,运算有结合律、交换律,每个元素有单位元、逆元)。

若满足有限可加,即:

AB=    f(AB)=f(A)+f(B)A\cap B=\varnothing \;\Longrightarrow\; f(A\cup B)=f(A)+f(B)
从而必有 f()=0f(\varnothing)=0

有限可加很强。其实意思就是每个 xGx \in G 会带个权 wxw_x,一个集合 SS 的权值 f(S)=xSwxf(S) = \sum_{x \in S} w_x,这就是充要的了。
为什么?因为根据定义,一个集合的权值可以拆成,两个不交且并为自身的集合之和,因此可以不断把 f(一个集合)f(一个集合) 分裂成 f(任意一个单元素集合)+f(剩下元素组成的集合)f(\text{任意一个单元素集合}) + f(\text{剩下元素组成的集合})。其中 f(剩下元素组成的集合)f(\text{剩下元素组成的集合}) 继续分拆,f(任意一个单元素集合)f(\text{任意一个单元素集合}) 直接累计进贡献。
不难发现,贡献来自包含的每个元素,因此有限可加相当于元素带权是充要的。

则有以下三条常用的容斥恒等式:

并转交f(i=1nAi)=k=1n(1)k+11i1<i2<<iknf(Ai1Ai2Aik)\boxed{\text{并转交}} \qquad f\left( \bigcup_{i=1}^n A_i \right) = \sum_{k=1}^n (-1)^{k+1} \sum_{1 \le i_1 < i_2 < \dots < i_k \le n} f\left(A_{i_1} \cap A_{i_2} \cap \dots \cap A_{i_k}\right) 交转并f(i=1nAi)=k=1n(1)k+11i1<i2<<iknf(Ai1Ai2Aik)\boxed{\text{交转并}} \qquad f\left( \bigcap_{i=1}^n A_i \right) = \sum_{k=1}^n (-1)^{k+1} \sum_{1 \le i_1 < i_2 < \dots < i_k \le n} f\left(A_{i_1} \cup A_{i_2} \cup \dots \cup A_{i_k}\right) 交转补的交f(i=1nAi)=k=0n(1)k1i1<i2<<iknf(Ai1cAi2cAikc)\boxed{\text{交转补的交}} \qquad f\left( \bigcap_{i=1}^n A_i \right) = \sum_{k=0}^n (-1)^k \sum_{1 \le i_1 < i_2 < \dots < i_k \le n} f\left( A_{i_1}^c \cap A_{i_2}^c \cap \dots \cap A_{i_k}^c \right)
其中 k=0k=0 的内层和按约定为 f(U)f(U)(即空交为 UU)。

看着不是很眼熟?把 f(S)f(S) 替换成 S|S|,现在看懂了吗?
几乎每篇讲容斥的博客都介绍了 f(S)=Sf(S) = |S|,即每个元素带 11 的权(不带权)时的形式;却没几篇博客讲这么一般的形式,怎么回事呢?

例题:P2429 制杖题

沿用原题面的变量名与记号。

简要题意:

求:
(x=1mx[i{1,2,,n}:pix])mod376544743\left( \sum_{x=1}^{m} x\, [\, \exists \, i \in \{1, 2, \dots, n\} : p_i \mid x\,] \right) \bmod 376544743
其中 1n,m1 \leq n, m,且保证满足以下条件中的其中一条:
  • n20,m109n \leq 20, m \leq 10^9
  • nm107nm \leq 10^7

思路

我做容斥的第一步,总是把符合要求的统计对象组成的集合 SS 表示成若干个集合的交/并的结果,其中若干个要在可控的范围内。
对于这题,SS 即为“与给定质数集有交集的自然数”,答案即为 xSx\sum_{x \in S} x
不难发现 SS 可以被表示为
T1T2TnT_1 \cup T_2 \cup \dots \cup T_n
RyR_y 为所有满足 1xm1 \leq x \leq myxy \mid xxx 组成的集合,那么上式的 TiT_i 即为 RpiR_{p_i}
因此我们要求的是 f(T1T2Tn)f(T_1 \cup T_2 \cup \dots \cup T_n),其中 f(U)=xUxf(U) = \sum_{x \in U} x
直接做肯定是不好做的,不然也不会用到容斥。我们使用第一个恒等式——并转交,那么有:
f(i=1nTi)=k=1n(1)k+11i1<i2<<iknf(Ti1Ti2Tik). f\left( \bigcup_{i=1}^n T_i \right) = \sum_{k=1}^n (-1)^{k+1} \sum_{1 \le i_1 < i_2 < \dots < i_k \le n} f\left(T_{i_1} \cap T_{i_2} \cap \dots \cap T_{i_k}\right).
其中 Ti1Ti2TikT_{i_1} \cap T_{i_2} \cap \dots \cap T_{i_k} 的意义即为“所有满足 1xm1 \leq x \leq mj{1,2,,k},pijx\forall \, j \in \{1, 2, \dots, k\},\, p_{i_j} \mid xxx 组成的集合”,等价于 Rlcm1jkpijR_{\operatorname{lcm}_{1 \leq j \leq k} p_{i_j}};又因为保证 pip_i 都是互不相同的素数,因此进一步简化为 Rj=1kpijR_{\prod_{j = 1}^k p_{i_j}}
f(Ry)f(R_y) 很好求,即为 ymy(my+1)2y \cdot \frac{\lfloor\frac{m}{y}\rfloor(\lfloor\frac{m}{y}\rfloor + 1)}{2},因此可以用一个式子来表示答案:
S{1,,n}(1)S+1(iSpi)miSpi(miSpi+1)2(mod376544743)\sum_{\varnothing\neq S\subseteq\{1,\dots,n\}} (-1)^{|S|+1}\left(\prod_{i\in S}p_i\right)\cdot \frac{\left\lfloor \frac{m}{\prod_{i\in S}p_i}\right\rfloor\left(\left\lfloor \frac{m}{\prod_{i\in S}p_i}\right\rfloor+1\right)}{2} \pmod{376544743}

代码

CPP
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using lll = __int128_t;

constexpr int N = 20, P = 376544743;

int p[N];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; ++i) {
        cin >> p[i];
    }

    lll ans = 0;
    auto dfs = [&](auto &&self, int dep, int mul, int cnt) {
        if (dep == n) {
            if (cnt) {
                lll res = ((m / mul + 1) * (ll)(m / mul) >> 1) * (lll)mul;
                ans += cnt & 1 ? res : -res;
            }
            return ;
        }
        self(self, dep + 1, mul, cnt);
        if ((ll)mul * p[dep] <= m) {
            self(self, dep + 1, mul * p[dep], cnt + 1);
        }
    };
    dfs(dfs, 0, 1, 0);
    cout << (int)(ans % P)<< '\n';
    return 0;
}
实际上,有了剪枝,时间复杂度一个充分紧的上界是 Θ(min(2n,nm))\Theta(\min(2^n, nm)),因此不需要对两个数据范围进行分别处理。

评论

6 条评论,欢迎与作者交流。

正在加载评论...