定义
形如 ∑ i = 0 2 n − 1 a i x i \sum_{i=0}^{2^n-1}a_ix^i ∑i=02n−1aixi,其中 i i i 是一个二进制数,表示 { 1 , 2 , . . . , n } \{1,2,...,n\} {1,2,...,n} 的一个子集。
基本操作
高维前缀和
即要求: c i = ∑ j [ j ∨ i = i ] a j c_i=\sum_j[j∨i=i]a_j ci=∑j[j∨i=i]aj
先考虑一维前缀和:
for(int i=1;i<=n;i++) a[i]+=a[i-1];
然后考虑二维前缀和:
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]+=a[i][j-1];
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]+=a[i-1][j];
以此类推,n维前缀和即为每次枚举一维,在这一维上做前缀和:
for(int i=0;i<n;i++)
for(int j=0;j<(1<<n);j++)
if(j&(1<<i)) a[j]+=a[j^(1<<i)];
这种做法即为 快速莫比乌斯变换,即FMT。
复杂度为
O
(
2
n
n
)
O(2^nn)
O(2nn)
高维后缀和
即要求: c i = ∑ j [ j ∧ i = i ] a j c_i=\sum_j[j∧i=i]a_j ci=∑j[j∧i=i]aj
与前缀和类似每次枚举一维做后缀和即可:
for(int i=0;i<n;i++)
for(int j=0;j<(1<<n);j++)
if(j&(1<<i)) a[j^(1<<i)]+=a[j];
或卷积
即要求: c i = ∑ j ∑ k [ j ∨ k = i ] a j b k c_i=\sum_j\sum_k[j∨k=i]a_jb_k ci=∑j∑k[j∨k=i]ajbk
若 a a a 经过 FMT 后的集合幂级数为 A A A, b b b 经过 FMT 后的集合幂级数为 B B B, c c c 经过 FMT 后的集合幂级数为 C C C,容易发现 C i = A i B i C_i=A_iB_i Ci=AiBi。
所以我们只需要对 a , b a,b a,b 分别做一次 FMT ,并将对应位相乘后做一次 FMT 的逆变换,即将刚才的过程反过来:
for(int i=0;i<n;i++)
for(int j=0;j<(1<<n);j++)
if(j&(1<<i)) a[j]-=a[j^(1<<i)];
复杂度为 O ( 2 n n ) O(2^nn) O(2nn)
与卷积
即要求: c i = ∑ j ∑ k [ j ∧ k = i ] a j b k c_i=\sum_j\sum_k[j∧k=i]a_jb_k ci=∑j∑k[j∧k=i]ajbk
与或卷积非常类似,按后缀和计算即可。
异或卷积
即要求: c i = ∑ j ∑ k [ j ⊕ k = i ] a j b k c_i=\sum_j\sum_k[j⊕k=i]a_jb_k ci=∑j∑k[j⊕k=i]ajbk
定义 F W T ( x ) i = ∑ j = 0 2 n − 1 ( − 1 ) ∣ i ∧ j ∣ x j FWT(x)_i=\sum_{j=0}^{2^n-1}(-1)^{|i∧j|}x_j FWT(x)i=∑j=02n−1(−1)∣i∧j∣xj。
若a和吧异或卷积后的结果为c,则 F W T ( c ) i = F W T ( a ) i ⋅ F W T ( b ) i FWT(c)_i=FWT(a)_i·FWT(b)_i FWT(c)i=FWT(a)i⋅FWT(b)i
证明:
F
W
T
(
c
)
i
=
∑
j
=
0
2
n
−
1
(
−
1
)
∣
i
∧
j
∣
c
j
FWT(c)_i=\sum_{j=0}^{2^n-1}(-1)^{|i∧j|}c_j
FWT(c)i=∑j=02n−1(−1)∣i∧j∣cj
= ∑ j = 0 2 n − 1 ( − 1 ) ∣ i ∧ j ∣ ∑ k = 0 2 n − 1 ∑ l = 0 2 n − 1 [ k ⊕ l = j ] a k b l \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =\sum_{j=0}^{2^n-1}(-1)^{|i∧j|}\sum_{k=0}^{2^n-1}\sum_{l=0}^{2^n-1}[k⊕l=j]a_kb_l =∑j=02n−1(−1)∣i∧j∣∑k=02n−1∑l=02n−1[k⊕l=j]akbl
= ∑ k = 0 2 n − 1 ∑ l = 0 2 n − 1 ( − 1 ) ∣ ( k ⊕ l ) ∧ i ∣ a k b l \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =\sum_{k=0}^{2^n-1}\sum_{l=0}^{2^n-1}(-1)^{|(k⊕l)∧i|}a_kb_l =∑k=02n−1∑l=02n−1(−1)∣(k⊕l)∧i∣akbl
= ∑ k = 0 2 n − 1 ∑ l = 0 2 n − 1 ( − 1 ) ∣ ( k ∧ i ∣ a k ⋅ ( − 1 ) ∣ ( l ∧ i ∣ b l \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =\sum_{k=0}^{2^n-1}\sum_{l=0}^{2^n-1}(-1)^{|(k∧i|}a_k·(-1)^{|(l∧i|}b_l =∑k=02n−1∑l=02n−1(−1)∣(k∧i∣ak⋅(−1)∣(l∧i∣bl
= ( ∑ k = 0 2 n − 1 ( − 1 ) ∣ k ∧ i ∣ a k ) ( ∑ l = 0 2 n − 1 ( − 1 ) ∣ l ∧ i ∣ l b l ) \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =(\sum_{k=0}^{2^n-1}(-1)^{|k∧i|a_k})(\sum_{l=0}^{2^n-1}(-1)^{|l∧i|lb_l}) =(∑k=02n−1(−1)∣k∧i∣ak)(∑l=02n−1(−1)∣l∧i∣lbl)
= F W T ( a ) i ⋅ F W T ( b ) i \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ =FWT(a)_i·FWT(b)_i =FWT(a)i⋅FWT(b)i
所以 c c c 即为对 a , b a,b a,b 分别求出 FWT 后对应相乘再做 FWT 的逆变换即可。
我们分别对每个位进行考虑。
对于第
i
i
i 位和第一个不包含
i
i
i 的集合
S
S
S,设
x
=
a
S
,
y
=
a
S
+
a
i
x=a_S,y=a_{S+a^i}
x=aS,y=aS+ai,则有新的
a
S
=
x
+
y
,
a
S
+
2
i
=
x
−
y
a_S=x+y,a_{S+2^i}=x-y
aS=x+y,aS+2i=x−y。具体代码如下:
for(int i=1;i<(1<<n);i<<=1){
for(int j=0;j<(1<<n);j+=(i<<1)){
for(int k=j;k<j+i;k++){
int x=a[k],y=a[k+i];
a[k]=x+y,a[k+i]=x-y;
}
}
}
复杂度为 O ( 2 n n ) O(2^nn) O(2nn)
子集卷积
即要求: c i = ∑ j ∑ k [ j ∧ k = ∅ , j ∨ k = i ] a j b k c_i=\sum_j\sum_k[j∧k=∅,j∨k=i]a_jb_k ci=∑j∑k[j∧k=∅,j∨k=i]ajbk
显然不能直接做或卷积。
考虑到
[
j
∧
k
=
∅
,
j
∨
k
=
i
]
[j∧k=∅,j∨k=i]
[j∧k=∅,j∨k=i] 的条件等价于
[
∣
j
∣
+
∣
k
∣
=
i
,
j
∨
k
=
i
]
[|j|+|k|=i,j∨k=i]
[∣j∣+∣k∣=i,j∨k=i],所以可以先将集合按元素个数分类,然后统计答案。
然鹅我们发现对应每一组都操作了 n n n 次 FWT,重复了。可以预处理出所有组的 FWT,对应每队直接对应位相乘累计答案。最后用 FWT 的逆运算返回即可。
复杂度为 O ( 2 n n 2 ) O(2^nn^2) O(2nn2)
子集卷积 exp
即要求: c i = ∑ i 1 , i 2 , . . . i k [ ∣ i 1 ∣ + ∣ i 2 ∣ + . . . + ∣ i k ∣ = ∣ i ∣ , i 1 ∨ i 2 ∨ . . . ∨ i k = i ] a i 1 a i 2 . . . a i k c_i=\sum_{i_1,i_2,...i_k}[|i_1|+|i_2|+...+|i_k|=|i|,i_1∨i_2∨...∨i_k=i]a_{i_1}a_{i_2}...a_{i_k} ci=∑i1,i2,...ik[∣i1∣+∣i2∣+...+∣ik∣=∣i∣,i1∨i2∨...∨ik=i]ai1ai2...aik
考虑按最高位分组,每一组中最多选择一个,所以答案即为所有组子集卷积后的答案。
复杂度为
∑
i
=
1
n
O
(
2
i
i
2
)
=
O
(
2
n
n
2
)
\sum_{i=1}^nO(2^ii^2)=O(2^nn^2)
∑i=1nO(2ii2)=O(2nn2)
多项式复合集合幂级数
即要求: c i = ∑ i = 0 n f i a i c_i=\sum_{i=0}^nf_ia^i ci=∑i=0nfiai,其中 a i a_i ai 为子集卷积。
在上一题的基础上记录当前还有几个要选。
G
i
,
j
G_{i,j}
Gi,j 表示合并完前
i
i
i 组后还需要再添加
j
j
j 个的方案数。初始即为
G
0
,
i
=
F
i
G_{0,i}=F_i
G0,i=Fi,每次添加一组即为
G
i
,
j
=
G
i
−
1
,
j
+
G
i
−
1
,
j
−
1
F
i
G_{i,j}=G_{i-1,j}+G_{i-1,j-1}F_i
Gi,j=Gi−1,j+Gi−1,j−1Fi,其中
F
i
F_i
Fi 表示第
i
i
i 组形成的集合。
复杂度为
∑
i
=
1
n
O
(
2
i
i
2
(
n
−
i
)
)
=
O
(
2
n
n
2
)
\sum_{i=1}^nO(2^ii^2(n-i))=O(2^nn^2)
∑i=1nO(2ii2(n−i))=O(2nn2)