FMT与子集卷积
求 C x = ∑ i ⋃ j = x a i ∗ b j C_x = \sum_{i\bigcup j = x}a_i*b_j Cx=∑i⋃j=xai∗bj
sol.
构造一个
F
M
T
(
A
)
=
∑
i
⊂
x
a
i
FMT(A) = \sum_{i\subset x}a_i
FMT(A)=∑i⊂xai
F
M
T
x
(
A
)
∗
F
M
T
x
(
B
)
=
∑
k
⊂
x
∑
i
⋃
j
=
k
a
i
∗
b
j
=
∑
k
⊂
x
C
k
=
F
M
T
x
(
C
)
FMT_x(A) * FMT_x(B) = \sum_{k \subset x}\sum_{i \bigcup j = k}a_i*b_j\\ =\sum_{k \subset x}C_k\\ = FMT_x(C)
FMTx(A)∗FMTx(B)=k⊂x∑i⋃j=k∑ai∗bj=k⊂x∑Ck=FMTx(C)
考虑如何快速构造这个 F M T ( A ) FMT(A) FMT(A)
很显然的一个事情 F M T ( A ) = F M T ( A 0 ) + F M T ( A 1 ) [ 用 二 进 制 表 示 集 合 , 分 别 有 没 由 前 面 的 第 一 个 元 素 ] FMT(A) = FMT(A_0) + FMT(A1) [用二进制表示集合,分别有没由前面的第一个元素] FMT(A)=FMT(A0)+FMT(A1)[用二进制表示集合,分别有没由前面的第一个元素]
那么可以直接二进制倍增来写。。。
for(int len = 2 ; len <= n ; len = (len << 1)){
for(int i = 0 ; i <= n ; i = i + len){
for(int j = 0 ; j < (len >> 1) ; j++){
f[i + j + (len >> 1)] += f[i + j];
}
}
}
大概就像这样就可以了
逆FMT的话如下
for(int len = 2 ; len <= n ; len = (len << 1)){
for(int i = 0 ; i <= n ; i = i + len){
for(int j = 0 ; j < (len >> 1) ; j++){
f[i + j] -= f[i + j + (len >> 1)];
}
}
}
就可以做掉了。。。。
FWT是这个玩意的加强版,专门来处理二进制操作卷积的
o r or or卷积,就是上面的FMT
a n d and and卷积:
需要构造一个 F M T ( A ) FMT(A) FMT(A)使得, F W T ( A ) x ∗ F W T ( B ) x = F W T ( C ) x FWT(A)_x * FWT(B)_x = FWT(C)_x FWT(A)x∗FWT(B)x=FWT(C)x
即:
∑
i
&
x
=
x
a
i
∗
∑
j
&
x
=
x
b
j
=
∑
(
i
&
j
)
&
x
=
x
a
i
∗
b
j
=
∑
i
&
x
=
x
c
i
\sum_{i \& x = x}a_i* \sum _ {j \& x = x}b_j = \sum_{(i \& j) \& x = x}a_i * b_j = \sum_{i \& x = x}c_i
i&x=x∑ai∗j&x=x∑bj=(i&j)&x=x∑ai∗bj=i&x=x∑ci
所以需要构造出:
F
W
T
x
(
A
)
=
∑
i
&
x
=
x
a
i
FWT_x(A) = \sum_{i \& x = x}a_i
FWTx(A)=i&x=x∑ai
大概就是这样
for(int len = 2 ; len <= n ; len = (len << 1)){
for(int i = 0 ; i <= n ; i = i + len){
for(int j = 0 ; j < (len >> 1) ; j++){
f[i + j] = f[i + j] + f[i + j + (len >> 1)];
}
}
}
xor卷积:
需要构造一个 F M T ( A ) FMT(A) FMT(A)使得, F W T ( A ) x ∗ F W T ( B ) x = F W T ( C ) x FWT(A)_x * FWT(B)_x = FWT(C)_x FWT(A)x∗FWT(B)x=FWT(C)x
即
∑
i
x
o
r
x
=
x
a
i
∑
j
x
o
r
x
=
x
b
j
=
\sum_{i \ xor\ x\ =\ x}a_i \sum_{j \ xor \ x \ = \ x}b_j =
i xor x = x∑aij xor x = x∑bj=
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vgia3cKl-1613121592741)(C:\Users\Administrator\Desktop\笔记\FWT2.PNG)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5jsO5avm-1613121592758)(C:\Users\Administrator\Desktop\笔记\FWT3.PNG)]
补一个证明
g
(
x
,
j
)
∗
g
(
x
,
k
)
=
(
−
1
)
∣
j
⋂
x
∣
+
∣
k
⋂
x
∣
=
(
−
1
)
(
j
x
o
r
k
)
⋂
x
g(x,j) * g(x , k) = (-1)^{|j\bigcap x| + |k\bigcap x|} = (-1)^{(j \ xor \ k) \bigcap x}
g(x,j)∗g(x,k)=(−1)∣j⋂x∣+∣k⋂x∣=(−1)(j xor k)⋂x
很显然的东西吖。。。。
所以就有代码
for(int len = 2 ; len <= n ; len = (len << 1)){
for(int i = 0 ; i <= n ; i += len){
for(int j = 0 ; j < (len << 1) ; j++){
int A = f[i + j] , B = f[i + j + k];
f[i + j] = A + B;
f[i + j + k] = A - B;
}
}
}
很显然的吧
逆的话,代码如下
for(int len = 2 ; len <= n ; len = (len << 1)){
for(int i = 0 ; i <= n ; i += len){
for(int j = 0 ; j < (len << 1) ; j++){
int A = f[i + j] , B = f[i + j + k];
f[i + j] = (A + B) / 2;
f[i + j + k] = (A - B) / 2;
}
}
}
FWT可以用来做一些高维前缀和的问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ibOaQY33-1613121592772)(C:\Users\Administrator\Desktop\笔记\FWT4.PNG)]
很显然就是 A L L = ∑ ( − 1 ) ∣ 与 n o w 相 关 的 维 度 ∣ a n o w ALL = \sum (-1)^{|与now相关的维度|}a_{now} ALL=∑(−1)∣与now相关的维度∣anow
与上面异或的定义 g ( x , i ) g(x,i) g(x,i)非常的相似(实际上就是同一个玩意)
实际上就是一个xor卷积的事情。。。。
入门题:luoguP3175 [HAOI2015]按位或
很容易列出方程
f
[
i
]
=
∑
j
∑
(
k
∣
j
)
=
i
(
f
[
k
]
+
1
)
∗
p
[
j
]
f
[
i
]
=
∑
j
!
=
i
∑
(
k
∣
j
)
=
i
(
f
[
k
]
+
1
)
∗
p
[
j
]
+
∑
k
∣
i
=
i
(
f
[
i
]
+
1
)
∗
p
[
k
]
f
[
i
]
=
∑
j
!
=
i
∑
(
k
∣
j
)
=
i
(
f
[
k
]
+
1
)
∗
p
[
j
]
+
∑
k
∣
i
=
i
p
[
k
]
1
−
∑
k
∣
i
=
i
p
[
k
]
f[i] = \sum_{j}\sum_{(k|j) \ =\ i}(f[k] + 1) * p[j]\\ f[i] = \sum_{j != i}\sum_{(k|j) \ =\ i}(f[k] + 1) * p[j] + \sum_{k | i\ =\ i}(f[i] + 1) * p[k]\\ f[i] = \frac {\sum_{j != i}\sum_{(k|j) \ =\ i}(f[k] + 1) * p[j] + \sum_{k | i\ =\ i}p[k]} {1 - \sum_{k | i\ =\ i}p[k]}
f[i]=j∑(k∣j) = i∑(f[k]+1)∗p[j]f[i]=j!=i∑(k∣j) = i∑(f[k]+1)∗p[j]+k∣i = i∑(f[i]+1)∗p[k]f[i]=1−∑k∣i = ip[k]∑j!=i∑(k∣j) = i(f[k]+1)∗p[j]+∑k∣i = ip[k]
s
o
l
1.
解
决
分
母
的
快
速
计
算
,
直
接
对
{
p
}
做
一
个
f
w
t
就
好
了
,
s
o
l
2.
分
子
第
二
项
同
s
o
l
1.
s
o
l
3.
分
子
第
一
项
最
烂
每
一
次
都
要
做
一
个
F
W
T
O
(
2
n
∗
2
n
∗
n
)
sol1.解决分母的快速计算,直接对\{p\}做一个fwt就好了,\\ sol2.分子第二项同sol1.\\ sol3.分子第一项最烂每一次都要做一个FWT\\ O(2^n * 2 ^ n * n)
sol1.解决分母的快速计算,直接对{p}做一个fwt就好了,sol2.分子第二项同sol1.sol3.分子第一项最烂每一次都要做一个FWTO(2n∗2n∗n)
很显然是不行的吧。。。
本人只能想到这种。。。
如果能做到动态维护 FWT卷积的话,这个式子还是很好做的。。。
。。。。
正解是 min-max容斥。。。。
我先去补一下二项式反演的坑
就好了,\
sol2.分子第二项同sol1.\
sol3.分子第一项最烂每一次都要做一个FWT\
O(2^n * 2 ^ n * n)
$$
很显然是不行的吧。。。
本人只能想到这种。。。
如果能做到动态维护 FWT卷积的话,这个式子还是很好做的。。。
。。。。
正解是 min-max容斥。。。。
我先去补一下二项式反演的坑