这篇文章在讲什么
相信大家都会FWT和FMT。
如果你不会,推荐你去看一下VFK的2015国家集训队论文。
设全集为\(U=\{1,2,\ldots,n\}\),假设我们关心的\(f_S\)中的集合\(S\)是\(U\)的子集。
给你\(c_i,d_i\),令
求
其中两个集合幂级数的乘积为集合并卷积(or)/集合对称差卷积(xor)中的一种。
不妨设\(d_S\)互不相同(否则可以用DP/组合数什么的搞一下)。
令
暴力做法
对于每一个集合幂级数暴力做一遍FMT/FWT,然后直接乘在一起,再变换回去。
时间复杂度:\(O(n4^n)\)
这个做法太慢了,因为它没有用到本题的特殊条件。
集合或卷积
对于一个集合幂级数\(f\),定义\(f\)的莫比乌斯变换为集合幂级数\(\hat f\),其中
反过来,定义\(\hat f\)的莫比乌斯反演为\(f\),由容斥原理可以得到
相信大家都熟悉以上内容。
回到我们要求的那条式子:
是不是发现和普通的莫比乌斯变换很像?
把所有\(a_S\)加上\(1\),把莫比乌斯变换的加法改成乘法,就可以得到\(\hat g_T\)了。
时间复杂度:\(O(n2^n)\)
集合对称差卷积
还是要用到那几条式子。
这个和沃尔什变换也很像,但是\({(-1)}^{|S\cap T|}\)只乘在了\(a_S\)上面,所以不能把\(a_S\)加\(1\)后做变种沃尔什变换。
但是我们可以再维护一个\(\hat h_T=\prod_S(1-a_S{(-1)}^{|S\cap T|})\),把沃尔什变换中的\(-\hat g_T\)全部换成\(\hat h_T\),就可以做了。
时间复杂度:\(O(n2^n)\)
代码
先坑着
(http://uoj.ac/submission/236983)