集合幂级数学习笔记

更好的阅读体验

定义集合幂级数 \(F(x)=\sum_{S}f_Sx^S\)\(S\) 是集合。单位元 \(\epsilon =x^{\varnothing}\)

集合幂级数的卷积

FMT / FWT 我们很熟知,其实是作用在集合幂级数上的快速变换。

对于一个集合运算(位运算)\(\otimes\),设变换 \(\hat F_S=\sum_{T}g(S, T)F_T\)。满足

\[\begin{aligned} \hat H_S&=\hat F_S\cdot\hat G_S\\ \sum_{i}g(S,i)H_i&=\sum_{j}g(S,j)F_j\sum_{k}g(S,k)G_k\\ \sum_{i,j}g(S,i\otimes j)F_iG_j&=\sum_{i,j}g(S,i)g(S,j)F_iG_j\\ \end{aligned} \]

我们可以发现 \(g(S,i\otimes j)=g(S,i)g(S,j)\),可以据此构造各种变换。

集合并卷积

也叫二进制数下的或卷积。

\(H=F\times G\)

\[H_S=\sum_{i\cup j=S}F_iG_j \]

现在 \(g(S,i\cup j)=g(S,i)g(S,j)\),构造变换 \(\hat F\)

\[\hat F_S=\sum_{T\subseteq S}F_T \]

即子集和,可以通过 FWT 解决,对二进制数按位考虑。也可看作高维前缀和。

IFWT 就是差分回去。

inline void FWT_or(int *f, int n, int op) {
	for (int mid = 1; mid < n; mid <<= 1)
		for (int i = 0; i < n; i += mid << 1)
			for (int j = 0; j < mid; ++j) {
				if (op == 1) f[i + mid + j] += f[i + j];
                else f[i + mid + j] += P - f[i + j];
                f[i + mid + j] %= P;
            }
}

集合交卷积(与卷积)同理,\(\hat F_S=\sum_{T\supseteq S}F_T\)

对称差卷积

也叫二进制数下的异或卷积。定义两个集合的对称差运算为 \(A\oplus B=\{x|[x\in A]\operatorname{xor}[x\in B]\}\),即二进制数的异或操作。

\(H=F\times G\)

\[H_S=\sum_{i\oplus j=S}F_iG_j \]

现在 \(g(S,i\oplus j)=g(S,i)g(S,j)\),构造变换 \(\hat F\)

\[\hat F_S=\sum_T(-1)^{|S\cap T|}F_T \]

通过 FWT 解决。

inline void FWT_xor(int *f, int n, int op) {
	for (int mid = 1; mid < n; mid <<= 1)
		for (int i = 0; i < n; i += mid << 1)
			for (int j = 0; j < mid; ++j) {
            	int x = f[i + j], y = f[i + mid + j];
                f[i + j] = (x + y) % P;
                f[i + mid + j] = (x - y + P) % P;
                if (op == -1) {
                	f[i + j] = 1ll * f[i + j] * inv2 % P;
                	f[i + mid + j] = 1ll * f[i + mid + j] * inv2 % P;
                }
            }
}

子集卷积

\(H=F\times G\)

\[H_S=\sum_{\substack{i\cup j=S\\i\cap j=\varnothing}}F_iG_j \]

在满足 \(i\cup j=S\) 的情况下,\(i\cap j=\varnothing\) 可以转化为 \(|i|+|j|=|S|\)

于是我们将集合幂级数 \(\sum_SF_Sx^S\)\(F_S\) 替换为占位多项式 \(F_S(z)=f_Sz^{|S|}\)。然后做集合并卷积,最后只要保留 \([z^{|S|}]F_S(z)\)。这样做其实是增加一维来去掉不合法的贡献。

由于一般情况下多项式的次数很低,使用 \(\mathcal O(n^2)\) 的多项式乘法更为合适。

模板题 代码

集合幂级数的进阶运算

若无说明,此节中集合幂级数的卷积为子集卷积,集合幂级数的变换为 FMT。

集合幂级数很多运算其实就是变换后的多项式运算。已经不知道自己是在学集合幂级数还是形式幂级数了。

求逆

\[F\times F^{-1}=\epsilon \]

把变换后的 \(\hat F\) 各项的多项式 \(f_S(z)\) 求逆,再逆变换回来就是 \(F^{-1}\)

多项式的 \(\mathcal O(n^2)\) 求逆:

\[\begin{aligned} \sum_{i=0}^{n}f_if^{-1}_{n-i}&=[n=0]\\ \sum_{i=1}^{n}f_if^{-1}_{n-i}+f_0f^{-1}_n&=[n=0]\\ \end{aligned} \]

那么可以递推,当 \(n=0\)\(f^{-1}_0=\frac{1}{f_0}\),其他情况

\[f^{-1}_n=-\frac{1}{f_0}\bigg(\sum_{i=1}^{n}f_if^{-1}_{n-i}-1\bigg) \]

ln & exp

定义

\[\exp(F(x))=\sum_{k=0}\frac{F(x)^{k}}{k!} \]

,要求 \([x^\varnothing]F(x)=0\)。注意 \(F(x)^k\)\(F(x)\)\(k\) 次幂,而这里 \(F(x)*F(x)\) 为子集卷积。

定义

\[\ln(F(x))=\sum_{k=1}\frac{(-1)^{k+1}(F(x)-x^\varnothing)^{k}}{k} \]

,要求 \([x^\varnothing]F(x)=1\)

当然求 \(\exp,\ln\) 是没法按定义式算的,应该和求逆一样,FWT 后对每个占位多项式做 \(\mathcal O(n^2)\) 的暴力 \(\exp,\ln\)

多项式 \(\mathcal O(n^2)\) \(\exp\)\(\ln\)

\[e^{F(x)}=G(x) \]

\(x\) 求导

\[\begin{aligned} \frac{\operatorname d e^{F(x)}}{\operatorname dx}&=\frac{G(x)}{\operatorname dx}\\ \frac{\operatorname dF(x)}{\operatorname dx}\frac{\operatorname de^{F(x)}}{F(x)}&=G'(x)\\ F'(x)e^{F(x)}&=G'(x)\\ F'(x)G(x)&=G'(x)\\ \end{aligned} \]

拆开并得到递推式

\[(n+1)g_{n+1}=\sum_{i=0}^n(i+1)f_{i+1}g_{n-i} \]

\[g_n=\frac 1 n \sum_{i=1}^{n}if_{i}g_{n-i} \]

,就可以递推求得 \(\exp(F(x))\) 了。

这个式子同样可以得到 \(\ln(F(x))\) 的递推式,拆出一项 \(f_{n+1}\)

\[\sum_{i=1}^{n-1}(i+1)f_{i+1}g_{n-i}+(n+1)f_{n+1}g_0=(n+1)g_{n+1} \]

得到

\[(n+1)f_{n+1}=(n+1)g_{n+1}-\sum_{i=0}^{n-1}(i+1)f_{i+1}g_{n-i} \]

\[f_n=g_n-\frac 1 n\sum_{i=1}^{n-1}if_{i}g_{n-i} \]

,就可以递推求得 \(\ln(F(x))\) 了。

导数

定义

\[(cx^S)'=\sum_{v\in S}cx^{S\setminus \{v\}} \]

所以一个集合幂级数的导数为

\[F(x)'=\sum_S\bigg(\sum_{v\notin S}f_{S\cup\{v\}}\bigg)x^S \]

分治卷积

留坑。

应用

参考资料

posted @ 2021-04-04 20:53  RenaMoe  阅读(485)  评论(0)    收藏  举报