积和式模 2 的次幂

题目链接

给定一个两边各有 nn 个点的二分图,判断完美匹配的个数是否是 44 的倍数。

n300n \le 300

完美匹配的个数即积和式。

来自论文的算法:求积和式模 44 的余数。

积和式定义:考虑所有选 nn 个不同行、不同列的数的方案,对每个方案中 nn 个数的乘积求和。

permA=pAi,pi\text{perm} A = \sum_{p}A_{i,p_i}

AA0101 矩阵时,有

premA=(1)nx{0,1}n(1)x1+x2++xni=1n(Ax)i\text{prem} A = (-1)^n\sum_{x \in \{0,1\}^n}(-1)^{x1+x2+\cdots+x_n}\prod_{i=1}^n(Ax)_i

证明可以考虑容斥:钦定某些列没有数被选。

观察到式子中间有一个 \prod ,由于我们要求这个东西模 44 的余数,如果它要造成贡献的话,AxAx 就至多有一个位置模 2200

考虑 AxAx 每一项模 22 的余数,由于至多只能有一个 00,因此可以枚举这个东西的取值,它只有 n+1n+1 种。

对于每种取值,通过高斯消元解出满足条件的所有 xx,再将每一组 xx 代入刚刚的式子中求出答案。

问题是,合法的 xx 的个数可能很大,因为需要枚举自由元的取值。

对这个矩阵做一些变换,记为 AA'

[A1,1A1,2A1,nv1A2,1A2,2A2,nv2An,1An,2An,nvn0001]\begin{bmatrix} A_{1,1}&A_{1,2}&\cdots &A_{1,n}&v_1\\ A_{2,1}&A_{2,2}&\cdots &A_{2,n}&v_2\\ \vdots&&&&\vdots\\ A_{n,1}&A_{n,2}&\cdots &A_{n,n}&v_n\\ 0&0&\cdots&0&1 \end{bmatrix}

显然 permA=permA\text{perm} A' = \text{perm} A

随机选取 vv,则期望 O(1)O(1) 组解:一组 xx 要有贡献,xn+1=1x_{n+1}=1(注意这一点,不能枚举 xn+1=0x_{n+1}=0,否则复杂度会假),因此翻转 vv 中的任意一位,AxA'x 也会翻转对应的一位,所以对于一个确定的 AxA'x,每一组 xx 成为它的解的概率都是 12n\frac 1{2^n}

直接写复杂度是 O(n4)O(n^4),使用 bitset 优化,复杂度为 O(n4ω)O(\frac {n^4}{\omega})

笔者想出了一个复杂度更好的算法。

引理:当 nn 阶方阵 AA22 意义下的秩小于等于 n3n-3 时(换句话就是模 22 意义下高斯消元后有至少 33 个自由元),有 permA0(mod4)\text{perm} A \equiv 0\pmod 4

证明留给读者。

把这种情况判掉就不需要随机化了,因为至多有 22 个自由元,也就至多有 44 个解。

之前算法的瓶颈在于枚举 AxAx 后需要 O(n3)O(n^3) 求解 xx 并计算贡献,这可以分为四个部分:

  • 高斯消元成上三角矩阵。
  • 判断是否有解(系数全 00 行的常数项是否为 00)。
  • 枚举每个自由元的取值,并算出每个非自由元。
  • xx 代入容斥式子计算贡献。

注意每次高斯消元的矩阵都是 AA,只有常数项不同,因此可以考虑像矩阵求逆一样在 AA 右边放一个单位矩阵进行一次消元,之后就可以 O(n2)O(n^2) 地由初始常数项直接计算消元后的常数项。

后三个部分的复杂度都不高于 O(n2)O(n^2),对于单个 AxAx 就可以做到 O(n2)O(n^2) 的复杂度,总复杂度 O(n3)O(n^3)

除高斯消元之外的部分(计算每个 AxAx 的贡献)还可以优化,虽然改变不了复杂度,但实际速度可以快很多倍。

实际上并不需要每次 O(n2)O(n^2) 计算消元后的常数项。考虑翻转 (Ax)i(Ax)_i,那么常数项中和 (Ax)i(Ax)_i 有关的位也会翻转,我们要求解的 AxAx 都是可以通过全 11 翻转至多一位得到的,预处理 AxAx11 的常数项,就可以 O(n)O(n) 得到其他 AxAx 的常数项。

判断是否有解直接判断即可,由于至多有 22 个自由元,复杂度 O(1)O(1)

求解 xx 也不需要先枚举每个自由元的取值,再算出每个非自由元。考虑消元后的常数项翻转了一些位,如果保持自由元取值不变,xx 也就是翻转了对应的位,在维护常数项的时候顺便维护 xxO(n)O(n) 的。

xx 代入容斥式子计算贡献是 O(n2)O(n^2) 的,但是我们只关心贡献模 44,如果 (Ax)i0(mod2)(Ax)_i\equiv 0\pmod 2,那么 x{0,1}n(1)x1+x2++xni=1n(Ax)i\sum_{x \in \{0,1\}^n}(-1)^{x1+x2+\cdots+x_n}\prod_{i=1}^n(Ax)_i 就必然是偶数了,只需要知道它是否是 44 的倍数,检验一下 (Ax)i(Ax)_i 即可。最后对 AxAx11 暴力计算即可。

使用 bitset 优化,复杂度 O(n3ω)O(\frac {n^3}{\omega}),除了读入和高斯消元外,其他部分复杂度不高于 O(n2ω)O(\frac {n^2}{\omega})

当计算积和式模 88 时,其他部分复杂度达到 O(n3ω)O(\frac {n^3}{\omega}),总复杂度仍然是 O(n3ω)O(\frac {n^3}{\omega})

O(n4ω)O(\frac {n^4}{\omega}) 代码:

O(n3ω)O(\frac {n^3}{\omega}) 代码: