二进制位运算
常见的二进制位运算有:或,与,异或。分别对应了FMT,FMT与FWT。
下面从易到难介绍这几种运算。一下默认幂级数长度为
2
n
2^n
2n。
FMT
即快速莫比乌斯变化,定义也挺简单的。
f
(
S
)
=
∑
T
⊂
S
g
(
T
)
f(S) = \sum_{T\subset S} g(T)
f(S)=T⊂S∑g(T)
实际上就是子集和,同理定义快速莫比乌斯反演,即将快速莫比乌斯变化反演即可
f
^
(
S
)
=
∑
T
⊂
S
(
−
1
)
∣
S
∣
−
∣
T
∣
g
(
T
)
\hat{f}(S) = \sum_{T\subset S} (-1)^{|S| - |T|}g(T)
f^(S)=T⊂S∑(−1)∣S∣−∣T∣g(T)
然后或卷积就明显可以通过此来优化。
同理就是与卷积。
定义是超集,反之亦然。
FWT
特别解决异或运算的。之后与 k k k进制 F W T FWT FWT一起写。
FST
就是failed system test
子集卷积。如果单纯做一个或卷积,那么势必答案是不对的,因为要求的条件实际上是
i | j == k && i & j == 0
而或卷积仅仅满足了第一个条件。那么多记一维表示应当有多少个即可。
k进制FWT
k进制下的异或任然是不进位加法,假设符号任然是
⊕
\oplus
⊕,并且是数组A * B = C。
从原理上讲,正变换是我们要做的事情是找到这样一个矩阵
w
w
w,使得原数组左乘上这个矩阵后还满足A * B = C。
逆变换是左乘这个矩阵的逆矩阵。那么考虑是什么意思
∑
i
⊕
j
=
k
A
i
∗
B
j
∗
w
(
x
,
i
)
∗
w
(
x
,
j
)
=
C
k
∗
w
(
x
,
k
)
\sum \limits_{i \oplus j = k} A_i * B_j * w(x, i) * w(x, j) = C_k * w(x, k)
i⊕j=k∑Ai∗Bj∗w(x,i)∗w(x,j)=Ck∗w(x,k)
对比系数可知
w
(
x
,
i
)
∗
w
(
x
,
j
)
=
w
(
x
,
k
)
  
(
i
⊕
j
=
k
)
w(x, i) * w(x, j) = w(x, k) \;(i \oplus j = k)
w(x,i)∗w(x,j)=w(x,k)(i⊕j=k)
那么我们的目的即使找到这样的一个矩阵。
那么这样的性质让我们想到单位根:
w
k
i
∗
w
k
j
=
w
k
i
⊕
j
w_{k}^{i} * w_{k}^{j}=w_{k}^{i\oplus j}
wki∗wkj=wki⊕j。从而联想到范德蒙德矩阵
[
1
1
1
.
.
.
1
1
w
k
1
w
k
2
.
.
.
w
k
k
−
1
1
w
k
2
w
k
4
.
.
.
w
k
2
(
k
−
1
)
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
w
k
k
−
1
w
k
2
(
k
−
1
)
.
.
.
w
k
(
k
−
1
)
(
k
−
1
)
]
\begin{bmatrix} 1& 1 & 1& ... & 1\\ 1& w_k^1& w_k^2& ... & w_k^{k - 1}\\ 1& w_k^2 & w_k^4& ... & w_k^{2(k - 1)}\\ ...& ...& ...& ...& ...\\ 1& w_k^{k - 1}& w_k^{2(k - 1)} & ... & w_k^{(k - 1)(k - 1)} \end{bmatrix}
⎣⎢⎢⎢⎢⎡111...11wk1wk2...wkk−11wk2wk4...wk2(k−1)...............1wkk−1wk2(k−1)...wk(k−1)(k−1)⎦⎥⎥⎥⎥⎤
然后我们也知道其逆矩阵
1
k
[
1
1
1
.
.
.
1
1
w
k
−
1
w
k
−
2
.
.
.
w
k
−
(
k
−
1
)
1
w
k
−
2
w
k
−
4
.
.
.
w
k
−
2
(
k
−
1
)
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
w
k
−
(
k
−
1
)
w
k
−
2
(
k
−
1
)
.
.
.
w
k
−
(
k
−
1
)
(
k
−
1
)
]
\frac{1}{k} \begin{bmatrix} 1& 1 & 1& ... & 1\\ 1& w_k^{-1}& w_k^{-2}& ... & w_k^{-(k - 1)}\\ 1& w_k^{-2} & w_k^{-4}& ... & w_k^{-2(k - 1)}\\ ...& ...& ...& ...& ...\\ 1& w_k^{-(k - 1)}& w_k^{-2(k - 1)} & ... & w_k^{-(k - 1)(k - 1)} \end{bmatrix}
k1⎣⎢⎢⎢⎢⎢⎡111...11wk−1wk−2...wk−(k−1)1wk−2wk−4...wk−2(k−1)...............1wk−(k−1)wk−2(k−1)...wk−(k−1)(k−1)⎦⎥⎥⎥⎥⎥⎤
然后不就完了?剩下的与正常的FWT一样的。就是答案由len / k的答案组合而来。同时要注意,如果是mod一个NTT质数的时候,有
w
n
0
=
g
m
o
d
−
1
n
w_n^0 = g^{\frac{mod - 1}{n}}
wn0=gnmod−1。
下面贴一份代码:
int wn[k];
inline int w(int x, int y) { return wn[(x * y) % k]; }
void FWT(int *a, int len, int coef) {
static int b[k];
int v;
for (int i = 1; i < len; i *= k) {
for (int j = 0; j < len; j += i * k) {
for (int k = j; k < j + i; k++) {
for (int d = 0; d < k; d++) {
b[d] = a[k + d * i];
a[k + d * i] = 0;
}
for (int d = 0; d < k; d++) {
v = k + d * i;
for (int _d = 0; _d < 4; _d++) {
a[v] = add(a[v], 1ll * w(d, coef * _d) * b[_d] % mod);
}
}
}
}
}
if (coef == -1) {
int Inv = qpow(len, mod - 2);
for (int i = 0; i < len; i++) a[i] = 1ll * Inv * a[i] % mod;
}
}
其中 w n [ i ] = ( g m o d − 1 k ) i wn[i] = (g^{\frac{mod - 1}{k}})^{i} wn[i]=(gkmod−1)i, c o e f coef coef为 1 1 1时为正变换, − 1 -1 −1时为逆变换。