原理

对于长度为 2n2^n 的数组 Ai,BiA_i,B_i 的卷积定义如下:

Ck=iopj=kAiBjC_k=\sum_{i\operatorname{op}j=k}A_iB_j

这里的 op\operatorname{op} 可以是与、或、异或。

与卷积

我们想找到一个可逆变换 FF,使得下面式子成立(无说明下面的加法和乘法都是逐位进行):

F(C)=F(A)F(B)F(C)=F(A)F(B)

并且我们希望他是线性的,即:

F(A+B)=F(A)+F(B)F(A+B)=F(A)+F(B)

这样就可以快速的计算了。

我们根据最高位是 0/10/1 将数组 AA 分为 A0,A1A_0,A_1,同理 B,CB,C 也是。

那么看原来的式子,由于只有 1and1=11\operatorname{and}1=1,其它的结果都是 00,因此:

C0k=iandj=kA0iB0j+A0iB1j+A1iB0jC1k=iandj=kA1iB1j\begin{aligned} C_{0k}&=\sum_{i\operatorname{and}j=k}A_{0i}B_{0j}+A_{0i}B_{1j}+A_{1i}B_{0j}\\ C_{1k}&=\sum_{i\operatorname{and}j=k}A_{1i}B_{1j} \end{aligned}

那么,对这两个式子用 FF 进行变换:

F(C0)=F(A0)F(B0)+F(A0)F(B1)+F(A1)F(B0)F(C1)=F(A1)F(B1)\begin{aligned} F(C_0)&=F(A_0)F(B_0)+F(A_0)F(B_1)+F(A_1)F(B_0)\\ F(C_1)&=F(A_1)F(B_1) \end{aligned}

两式相加可以得到:

F(C0+C1)=F(A0+A1)F(B0+B1)F(C_0+C_1)=F(A_0+A_1)F(B_0+B_1)

所以,我们可以这样构造 F(C)F(C)

F(C)=(F(C0)+F(C1),F(C1))F(C)=\Big(F(C_0)+F(C_1),F(C_1)\Big)

就可以使得前半部分和后半部分都满足:

F(C)=F(A)F(B)F(C)=F(A)F(B)

那么,我们还需要研究一下这个变换的逆变换,这里上标 * 表示当前这个数组是变换后的数组:

F1(C)=(F1(C0)F1(C1),F1(C1))F^{-1}(C^*)=\Big(F^{-1}(C_0^*)-F^{-1}(C_1^*),F^{-1}(C_1^*)\Big)

所以我们构造出了一种快速求与卷积的方式,即先进行 FF 变换,然后逐位相乘,最后通过逆变换 F1F^{-1} 复原。

或卷积

同样的分类方法,我们可以将所有的数组分成两部分,然后:

C0k=iorj=kA0iB0jC1k=iorj=kA0iB1j+A1iB0j+A1iB1j\begin{aligned} C_{0k}&=\sum_{i\operatorname{or}j=k}A_{0i}B_{0j}\\ C_{1k}&=\sum_{i\operatorname{or}j=k}A_{0i}B_{1j}+A_{1i}B_{0j}+A_{1i}B_{1j} \end{aligned}

设满足要求的变换是 GG,那么两边取 GG 可以得到:

G(C0)=G(A0)G(B0)G(C1)=G(A0)G(B1)+G(A1)G(B0)+G(A1)G(B1)\begin{aligned} G(C_0)&=G(A_0)G(B_0)\\ G(C_1)&=G(A_0)G(B_1)+G(A_1)G(B_0)+G(A_1)G(B_1) \end{aligned}

同上,可以构造出这样的变换:

G(C)=(G(C0),G(C0)+G(C1))G(C)=\Big(G(C_0),G(C_0)+G(C_1)\Big)

逆变换是:

G1(C)=(G1(C0),G1(C1)G1(C0))G^{-1}(C^*)=\Big(G^{-1}(C_0^*),G^{-1}(C_1^*)-G^{-1}(C_0^*)\Big)

异或卷积

分类方法同上:

C0k=ij=kA0iB0j+A1iB1jC1k=ij=kA0iB1j+A1iB0j\begin{aligned} C_{0k}&=\sum_{i\oplus j=k}A_{0i}B_{0j}+A_{1i}B_{1j}\\ C_{1k}&=\sum_{i\oplus j=k}A_{0i}B_{1j}+A_{1i}B_{0j} \end{aligned}

设满足要求的变换是 HH,那么可以得到:

H(C0)=H(A0)H(B0)+H(A1)H(B1)H(C1)=H(A1)H(B0)+H(A0)H(B1)H(C_0)=H(A_0)H(B_0)+H(A_1)H(B_1)\\ H(C_1)=H(A_1)H(B_0)+H(A_0)H(B_1)

两式相加相减:

H(C0+C1)=H(A0+A1)H(B0+B1)H(C0C1)=H(A0A1)H(B0B1)H(C_0+C_1)=H(A_0+A_1)H(B_0+B_1)\\ H(C_0-C_1)=H(A_0-A_1)H(B_0-B_1)

构造变换:

H(C)=(H(C0)+H(C1),H(C0)H(C1))H(C)=\Big(H(C_0)+H(C_1),H(C_0)-H(C_1)\Big)

因此逆变换为:

H1(C)=12(H1(C0)+H1(C1),H1(C0)H1(C1))H^{-1}(C^*)=\frac{1}{2}\Big(H^{-1}(C_0^*)+H^{-1}(C_1^*),H^{-1}(C_0^*)-H^{-1}(C_1^*)\Big)

对于上面的所有变换,最终数组长度为 11 时,保留其为那个数字本身即可,因为这三个卷积对于只有一个数字的情况都是普通的乘法。

Binary Table

给定 n20n\le 20m105m\le 10^5 列表格,每个元素是 0/10/1,每次操作选择一行或一列翻转,问经过若干次操作后表格中最少有多少个 11

首先,翻转等价于 1\oplus 1。而异或具有交换率,所以我们可以认为先进行行操作,最后统一进行列操作。

将第 ii 列看作一个二进制数 viv_i,当行操作结束时,相当于给每一列选择了一个 0x2n10\le x\le 2^n-1 使得 vivixv_i\gets v_i\oplus x

由于最后进行列操作,所以每一列的贡献 fv=min{popcountv,npopcountv}f_v=\min\{\operatorname{popcount}v,n-\operatorname{popcount}v\}

枚举所有的 xx,最后的结果就是:

minx=02n1{i=1mfvix}\min_{x=0}^{2^n-1}\left\{\sum_{i=1}^m f_{v_i\oplus x}\right\}

一个常见的套路是将枚举每一个 viv_i 转化为枚举 viv_i 的个数,设 gv=i=1m[vi=v]g_v=\sum_{i=1}^m [v_i=v],那么目标式转化为:

minx=02n1{v=02n1fvxgv}=minx=02n1{ij=xfigj}\min_{x=0}^{2^n-1}\left\{\sum_{v=0}^{2^n-1} f_{v\oplus x}g_v\right\}=\min_{x=0}^{2^n-1}\left\{\sum_{i\oplus j=x} f_ig_j\right\}

因此求一个 ffgg 的异或卷积求参数的最小值就是答案。

Little Pony and Elements of Harmony

给定 m20,t1018,p109m\le 20,t\le 10^{18},p\le 10^9,令 n=2mn=2^m,给定长度为 nn 的数组 e0[]e_0[-] 和长度为 m+1m+1 的数组 b0bmb_0\sim b_m,定义 eie_iei1e_{i-1} 的递推式:

ei[u]=vei1[v]b[popcount(uv)]e_i[u]=\sum_{v}e_{i-1}[v]b[\operatorname{popcount}(u\oplus v)]

et[]modpe_t[-]\bmod p。注意 pp 不保证是一个质数。

显然,我们令 f[x]=b[popcountx]f[x]=b[\operatorname{popcount} x],就会有:

ei[u]=vei1[v]f[uv]=xy=uei1[x]f[y]\begin{aligned} e_i[u]&=\sum_{v}e_{i-1}[v]f[u\oplus v]\\ &=\sum_{x\oplus y=u} e_{i-1}[x]f[y] \end{aligned}

那么 ei=ei1fe_i=e_{i-1} * f,则 et=e0fte_t=e_0 *f^t。两边取一个 FWT 就会得到:

F(et)=F(e0)[F(f)t]F(e_t)=F(e_0)[F(f)^t]

这里的次方是逐位求次方。

还有一个问题,就是 pp 不一定是一个质数,那么 22 的逆元就不一定存在。这里修改一下逆变换的过程,设答案数组是 aa,如果逆变换过程中不进行除 22 的操作,那么最终得到的数组就会是 2mai2^m a_i。只需要将模数预先乘 2m2^m,设我们得到的结果数组是 xx,就会有:

2maixi(mod2mp)aixi2m(modp)\begin{aligned} 2^m{a_i}&\equiv x_i \pmod { 2^mp}\\ a_i&\equiv \frac{x_i}{2^m}\pmod {p} \end{aligned}

这里 2mp2^m p 比较大,乘法需要用到 int128