集合幂级数瞎扯
集合幂级数瞎扯
给自己写的,欢迎指正。
位运算卷积,核心记住:\(c(0/1,x)c(0/1,y)=c(0/1,j\oplus k)\)
由于最后要求逆,所以设计的矩阵要可逆。
or 运算:
and 运算:
xor 运算:
矩阵可能不止一种,理解方式也不止一种。
void FWT(ll* P,ll op=1)
{
for(ll j=1;j<m;j<<=1)for(ll i=0,x=0,y=0;i<m;i++,i+=i&j)
x=P[i],y=P[i+j],P[i]=(x+y)*op%H,P[i+j]=(x-y+H)*op%H;
}
书写的时候不需要写矩阵,这个代码是学 xyf 大蛇的,精炼。
子集卷积:
考虑把它改写成:\(x^Sy^{|S|}\) 那么没有交集就意味着 \(|A|+|B|=|A\cap B|\),那么对于不同的 \(y\) 分别做 FWT 然后再做多项式卷积。
FWT 大多时候只是最外层的壳子,通常在最开始的解壳最后的时候加壳,可恶的是加了壳子之后调试难度大大增加。
FWT 的位矩阵还是太超前了,考虑实际意义,or 的 FWT 相当于子集和,and 的 FWT 相当于超级和,那么可以很快的求出一个点对另一个点的贡献,or 和 and 的 IFWT 贡献系数是 \((-1)^{|S|-|T|}\)
xor 下,\(S\) 到 \(T\) 的贡献是 \((-1)^{|S \& T|}\),所以在初始值很少或者值出现地位置有规律的时候是不需要做 FWT 的,IFWT 的贡献系数是 \(\frac{1}{2^n}(-1)^{|S \& T|}\)
UOJ310:一个异或和为 \(0\) 的集合的贡献为 \(2^{|S|}\),那么幂级数就是 \((1+2x^{a_i})\) 做异或卷积,暴力做法是对每个 \(i\) FWT,显然爆了,知道每一个点对其他点的贡献系数,那么一个点收到的贡献只能可能是 1 或者 -3,我们知道系数和以及个数和,就可以解出 1 和 -3 分别的个数,然后 IFWT 就好了。
CF1119H:上面只有两个位置有值,这里是 \(k\) 个,考虑通用解法,还是先算出所有的和的 FWT,然后考虑算出 \(2^{k}\) 每种的贡献次数,考虑算出 \(2^{k}\) 种异或和的和的 FWT 然后这个等于贡献次数的 FWT,证明,然后 IFWT 就可以算贡献次数了。
ABC367G:考虑类似上面求出贡献数组,但是多了一个 \(m\) 的倍数,考虑在另一维做暴力循环卷积即可。
QOJ5089:求的是每个点度数均为偶数的子图,\(\prod (1+x^{u_i,v_i}y)\) 做异或卷积,考虑算 \((1-y)\) 的贡献次数,即为边里恰好有一个点在集合 \(S\) 中,直接递推转移即可,最后只用算 \(x^0\),那么相当于就是所有的系数和,组合数暴力计算即可。
CF662C:考虑如果确定了行的翻转次数,列的贡献就是 \(\min(|S|,n-|S|)\),脑筋急转弯一下,那么 \(f\oplus g=h\),\(f\) 是每一列的原状态,\(g\) 是贡献,\(h\) 就是行的翻转情况。
子集卷积既可以刻画不交又可以刻画选中了全集,所以大多数时候可以网上套。
CF2070F :不一定是交集为空,可以根据实际意义改写 \(x^Sy^{|S\cap T|}\)
CF1034E:子集卷积复杂度暴了,至于很小,考虑设 \(y=4\),最后直接除以 \(4^{|y|}\)
CF1326F2:容斥,计算钦定某些位置为 \(1\) 的位置,那么把一看成边,会形成若干连通块,显然顺序不影响,那么就是 \(p(n)\) 个,考虑算出每个子集形成一条链的方案数,然后大力 FWT 之后枚举拆分数得出方案数,最后 IFWT 回去即可(只用求一项,算贡献即可)
与多项式操作(dp)结合,难度更为巨大。
P6570:即为 \(\prod (x^{\empty+x^{a_i}})\) 乘法是子集卷积,考虑 ln+exp 即可,可以暴力实现多项式操作:this。
P6846:我的 DAG 容斥 /ll,考虑钦定入读为 \(0\) 的独立集 \(T\) 贡献为 \((-1)^{|T|-1}\) ,设集合幂级数 \(G\),贡献即为 \(\frac{1}{1-G}\),还是 FWT 之后求逆即可。
loj154:无敌了,考虑 FWT 之后求 \(exp_{\le k}\),还得套多项式快速幂,恶心。
AGC034F:一种很好的梳理方式为:
\((f_0,f_1,\cdots,f_{2^n-1})\oplus (p_0,p_1,\cdots ,p_{2^n-1})=(f_{0}+2^n-1,f_1-1,\cdots,f_{2^n-1})\)
\((f_0,f_1,\cdots,f_{2^n-1})\oplus (p_0-1,p_1,\cdots ,p_{2^n-1})=(2^N-1,-1,\cdots -1)\)
直接上 FWT 和求逆,但是第零项可能除到 \(0\) 很讨厌,一种做法是考虑把 \(f_0\) 设出来然后系数偏移一下,还有一种是依据 \(IFWT(f_0)=0\) 反推出 FWT 第 \(0\) 项的系数。
P5326:金典牢题,跟上面一样,只不过 \(p_S\) 只有在 \(2^i\) 有系数,考虑手动 FWT ,推出 \(FWT(F)\),(注意第 \(0\) 项),然后再手动 IFWT,最后大力 DP,这也太牛了。
CF1713F:考虑先推到对角线上再推到边上,两边都是超级/子集和,直接 IFWT/FWT 回去就好了。
ABC288G:考虑从 \(B\) 反推系数,大概还是类似 FWT 按位考虑贡献,设计矩阵,手动求逆即可。
还有亿些 K 进制 FWT 题目,好像挺厉害的,下次再学把(会有下次吗)。