集合幂级数运算(施工中)

集合幂级数运算

前置知识:FWT

子集卷积

link

给定 \(B,C\),求 \(A_S=\sum_{T\subseteq S} B_TC_{S/T}\)。即求 \(B,C\) 的无交并卷积。

\(S,T\) 无交等价于 \(|S|+|T|=|S\cup T|\),因此可以多记一维表示集合的大小,即设 \(A_{i,S}=[|S|=i]A_S\)

\(A_i,B_i\) 分别做集合并变换,转移为 \(A_{i,S}B_{j,T}\to C_{i+j,S\cup T}\)。最后对 \(C\) 做逆变换,答案为 \(C_{S}=C_{|S|,S}\)

复杂度是 \(O(n^22^n)\)

核心代码:

fu(i,0,1<<n) read(a[popc(i)][i]);
fu(i,0,1<<n) read(b[popc(i)][i]);
fo(i,0,n) fwt_or(a[i],1),fwt_or(b[i],1);
fo(i,0,n) {
    fo(j,0,i) fu(k,0,1<<n) inc(c[i][k],(ll)a[j][k]*b[i-j][k]%mod);
    fwt_or(c[i],-1);
}
fu(i,0,1<<n) write(c[popc(i)][i],' ');

例一:州区划分

求逆

link

给定 \(F\),求一个集合幂级数 \(G\),使得 \(F,G\) 在系数对 \(998244353\) 取模时,做子集卷积的结果等于 \(1\)(即只有 \(x^{\varnothing}\) 一项的系数为 \(1\))。

条件等价于 \(\sum _{T\subseteq S} F_T G_{S/T}=[S=\varnothing]\)

显然有 \(G_{\varnothing}=\frac 1{F_{\varnothing}}\)。当 \(S\ne \varnothing\) 时,我们把 \(T=\varnothing\) 一项分离出来还可以得到 \(G_S=-\frac1{F_{\varnothing}} {\sum _{T\subsetneqq S}F_{S/T} G_{T}}\)

延续子集卷积的思想,可以多记一维表示集合大小,从小到大扫 \(|S|\),依次得到每一种 \(|S|\) 的所有 \(G_S\)

转移依旧是 \(F_{i,S}G_{j,T}\to F_{i+j,S\cup T}\),要在全部转移完后再最后做逆变换。

注意到由于是不交并卷积,所以对于不满足集合大小限制的位置可以不用清空,不影响答案。

复杂度是 \(O(n^22^n)\)

例二:卡牌

link

半在线卷积

exp

给定一个集合幂级数 \(F(x)\),求 \(e^{F(x)}\),系数取模。

其中 \(e^{F(x)}\) 是一个集合幂级数,根据泰勒展开有:

\[e^{F(x)}=\sum _{n\ge 0} \frac {F^n(x)}{n!} \]

做法 1:

考虑 exp 的组合意义,即选出若干集合,使得它们的无交并等于 \(S\),贡献为这些集合权值的乘积,集合之间没有顺序。式子中的 \(n!\) 是取消顺序用的,但和我们的做法不太相关。

考虑给集合一个顺序,可以以集合中的最大元素作为顺序,设 \(A_i=1+\sum_S [\max(S)=i]F_Sx^S\),那么求所有 \(A_i\) 的子集卷积就是答案。

复杂度是 \(\sum _{i=0}^n O(i^22^i)=O(n^22^n)\),有比较大的常数,但是这个做法可以通过非素数模数的版本。

做法 2:利用半在线卷积

ln

posted @ 2026-05-07 07:32  dengchengyu  阅读(17)  评论(0)    收藏  举报