今天学习莫比乌斯变换。
前置技能
fwt与运算。
其实就是这个的低配版本
干嘛用的?
用来快速计算子集卷积。
就是说,
f
[
i
]
=
∑
g
[
j
]
∗
h
[
k
]
(
j
∣
k
=
i
&
&
j
&
k
=
0
)
f[i]=\sum {g[j]*h[k]}{(j|k=i\&\&j\&k=0)}
f[i]=∑g[j]∗h[k](j∣k=i&&j&k=0)
核心思想
打包运算。
首先我们考虑它的低配版本。
f
[
i
]
=
∑
g
[
j
]
∗
h
[
k
]
(
j
∣
k
=
i
)
f[i]=\sum {g[j]*h[k]}{(j|k=i)}
f[i]=∑g[j]∗h[k](j∣k=i)
我们定义f1[i]表示所有i的子集的和。
不如直接看图算了。.
这样我们就实现了打包运算:h’[i]表示所有下标是i的子集的答案之和。
所以呢?
考虑我们算重了什么。
我们会把有交集的下标算进去,比如
2
&
3
=
2
2\&3=2
2&3=2实际上是不行的。
怎么办?
统计位数。
令f[i][j]表示下标为i,i中有j个1的f的对应变换,即只考虑所有
p
o
p
c
o
u
n
t
(
i
)
=
=
j
popcount(i)==j
popcount(i)==j的原f数组为对应值。
然后枚举两边的1个数,只有所有1的个数与下标实际1的个数相同的才会产生贡献。
(否则就是打包出锅了。)
怎么反演?
最后对于每个下标处相乘时多项式反演即可。
用
n
2
n^2
n2即可。
小朋友化式子法