SetAndSet

给出一个长度为的非负整数序列,要求将中的元素染红或染蓝,使得:

  1. 至少有一个红色元素;
  2. 至少有一个蓝色元素;
  3. 红色元素的按位与等于蓝色元素的按位与。

问有多少种合法的染色方案。

容斥

考虑二进制下第位。如果所有数的第位都是 1,那么就可以不管这一位。否则,这一位为的数不能全部分在一个集合。

考虑容斥,容斥哪些位的分在同一集合。那么转化为无限制减去全部分在同一集合,用并查集统计有多少个连通块,容斥贡献就是,减 2 是因为要非空。

使用 DFS 写容斥可以少一个,时间复杂度

代码

Endless Spin

给出个球排成一排。初始时每个球都是白的。每次从个区间中等概率选择一个区间,把里面的求染黑。问期望多少次可以把所有球染黑。

期望 容斥 DP

设随机变量表示第个球被染黑的时间,且。那么答案可以表示为

对于集合,我们需要求出,选到至少一个球的期望时间。期望是概率的倒数,转化为选到至少一个球的概率。那么假设对于集合的元素,有个区间可以让我们至少选到一个元素,那么概率就为,因此期望为

那么如果我们求出

答案就为

考虑“至少选到一个”不好求,我们转化为,求一个都选不到。设表示考虑前个点,有恰好个区间,最后一个被选的点到第个点的距离为,使得这个区间选不到白点的方案数(可以理解为这个概率的出现次数),再记一个表示这个部分的容斥系数:

那么答案为

高精度用 python 打表即可。

时间复杂度

代码

代码 python

CTS2019 随机立方体

有一个的立方体,立方体中每个格子上都有一个数,如果某个格子上的数比三维坐标至少有一维相同的其他格子(三个方向的格子的集合)里的数都要大的话,我们就称它是极大的。

现在将随机填入到个格子中,使得每个数恰出现一次,求恰有个极大的数的概率,对取模。

二项式反演 概率 组合数 线性求逆元

表示恰有个的概率。那么设表示至少有个的概率。那么每个就被计算了次,根据二项式反演,得到

考虑求。显然我们可以钦定个最大值,那么不妨设这个最大值的位置分别在的地方。并且我们要求。然后这个数是各自的 3 个方向上切面的最大值。容易发现,这形成了一个树形结构(可以看二维的情况模拟得到),那么我们的问题等价于,给一棵树的每个结点分配一个标号,使得每个点是子树最大值的概率。答案即为每个子树的大小之和。由于这棵树的形态特殊,因此实际上可以得到概率为

然后考虑这个最大值的位置(刚才我们是钦定的位置,没有讨论过),那么第一个有种选择,第二个有种选择,以此类推。则总方案数为。因此得到

显然是可以递推的:

那么我们线性求的逆元即可(注意,线性求逆元在含有 0 的时候有 bug,但是本题中不会出现这种情况),时间复杂度

代码

Square Constraints

原题目的限制可以表示为

考虑容斥下界。那么我们就枚举这个数中有个数。假设我们确定了个数,这个个数的限制是,所有数的限制是(注意到是包含了的),求这样的方案数。那么我们把每个数的限制从小到大排序,形成一个长度为的数组,那么答案为

但是这个数是不确定的。我们考虑把放在一起升序排序得到序列,并且我们把标记为a,把标记为b,把标记为c。那么的标记数组一定长成aaccac...bbbbb的形式,即ac全在前面,b在后面的形式。

相当于我们从这个数中选择个出来,满足对于的部分我们选择(即所有的c必选),然后我们选择(相当于选择a),然后剩下的选(相当于选择b)。

由于都是非递增的,因此相当于你选了第a就不能选第b。因此我们就转化为了求出,选个数的限制为的容斥贡献和。这个可以 DP 做,设表示在考虑前个数以及对应的前若干个b,我们选a的容斥贡献和。设表示当时它对应的b的位置,方便转移。那么贡献和就是

代码

Two Histograms

对于一个方案,如果存在使得,那么我们就把它变成。如果不存在,就是一个“合法”的方案。

我们只需要统计出所有“合法”的方案就是答案。证明见官题。

考虑容斥,则答案为

代码

HamiltonianPaths

有一个个点的无向简单图,你把它复制次变成一个个点的图,然后求补图的哈密尔顿路径(有向)的数目。

设原图上的边为不合法的边,我们要求不能经过不合法的边。考虑容斥,问题转化为,钦定经过条不合法的边,其他点无限制,问哈密尔顿路径的数目,这样的容斥贡献是

我们先不考虑复制的操作,考虑在原图及其补图上求出经过条不合法的边的哈密尔顿的路径数的容斥贡献和。

更具体地,设表示在原图上,点集结尾的哈密尔顿路径数,乘上容斥系数,这个可以 DP 求出:

那么设表示在原图上点集的哈密尔顿路径数,即

于是,我们设表示在原图上点集被分成条路径的方案数(单点算一条路径),显然可以枚举第一个点 / 最后一个点所在的子集,用转移:

那么,我们就求出了把原图划分为不合法的路径的方案数的容斥贡献和。考虑复制了遍,能否求出新图的

答案是可以。注意到复制遍的即为,因此做次 FFT 即可(用快速幂)。

求出了这个,那么答案就为,表示你把这条不合法路径用条合法的边(合法的边就是补图上的边)连起来,连成一个哈密尔顿通路的方案数,显然这条路径的顺序可以任意安排,因此有种方案。至于容斥系数在一开始的时候就计算过了,因此不用乘

时间复杂度

代码

ZJOI2016 小星星

我们把双射放缩为一个函数,那么我们希望中,都出现过。

考虑容斥,我们枚举哪些值没有出现(即我们允许多个点对应一个点)。没有出现,我们就直接在图上删掉这个点。于是考虑 DP,设表示考虑的子树,且和原图上的对应,问有多少种对应方案。转移时枚举每个儿子的对应方案:

DP 的复杂度是的,加上枚举的复杂度,总复杂度

代码

Fireflies

问题可以通过一堆定理转化为,求的解的方案数。

考虑容斥,转化为枚举集合内的元素不满足限制,则可以得到

直接做的复杂度为,不能接受。考虑 meet-in-middle。

根据范德蒙德卷积

那么我们把拆成两个集合,可以得到

因此,设,那么上式可以等价地表示为

那么原式即为

设出函数来简化问题

注意。那么原式进一步简化为

那么我们在求和的过程中,只需要保证即可。这个可以排序后双指针实现,再加上前缀和优化,就可以合并答案。可以各自递推求出:

注意,使用下降幂计算组合数,上部是可以为负数的:

注意,范德蒙德卷积是可以做负数的。

总复杂度

代码