定义
A
A
A和
B
B
B均是长度为
n
=
2
k
n=2^k
n=2k的数组。定义
A
0
A_0
A0为这个数组的前
2
n
−
1
2^{n-1}
2n−1项,
A
1
A_1
A1为这个数组的后
2
n
−
1
2^{n-1}
2n−1项,那么有
A
=
(
A
0
,
A
1
)
A=(A_0,A_1)
A=(A0,A1)。
A
+
B
=
(
A
[
0
]
+
B
[
0
]
,
A
[
1
]
+
B
[
1
]
,
.
.
.
,
A
[
n
−
1
]
+
B
[
n
−
1
]
)
A+B=(A[0]+B[0],A[1]+B[1],...,A[n-1]+B[n-1])
A+B=(A[0]+B[0],A[1]+B[1],...,A[n−1]+B[n−1])
A
∗
B
=
(
A
[
0
]
∗
B
[
0
]
,
A
[
1
]
∗
B
[
1
]
,
.
.
.
,
A
[
n
−
1
]
∗
B
[
n
−
1
]
)
A*B=(A[0]*B[0],A[1]*B[1],...,A[n-1]*B[n-1])
A∗B=(A[0]∗B[0],A[1]∗B[1],...,A[n−1]∗B[n−1])
A
@
B
=
(
∑
i
@
j
=
0
A
[
i
]
∗
B
[
j
]
,
∑
i
@
j
=
1
A
[
i
]
∗
B
[
j
]
,
.
.
.
,
∑
i
@
j
=
n
−
1
A
[
i
]
∗
B
[
j
]
)
A@B=(\sum_{i@j=0}A[i]*B[j],\sum_{i@j=1}A[i]*B[j],...,\sum_{i@j=n-1}A[i]*B[j])
A@B=(∑i@j=0A[i]∗B[j],∑i@j=1A[i]∗B[j],...,∑i@j=n−1A[i]∗B[j])
目标
给出 A , B A,B A,B,求 C = A @ B C=A@B C=A@B。
快速沃尔什变换
快速沃尔什变换(简称FWT),就是用来解决这样一类问题的算法。其中
@
@
@运算可以是异或,与,或之类的位运算。
这里主要介绍异或运算。
XOR
根据异或运算的性质,不难得到
A
@
B
=
(
A
0
⊕
B
0
+
A
1
⊕
B
1
,
A
0
⊕
B
1
+
A
1
⊕
B
0
)
A@B=(A_0\oplus B_0+A_1\oplus B_1,A_0\oplus B_1+A_1\oplus B_0)
A@B=(A0⊕B0+A1⊕B1,A0⊕B1+A1⊕B0)。
且不难验证
⊕
\oplus
⊕运算满足交换律,分配律和结合律。
定义运算
F
w
t
(
A
)
Fwt(A)
Fwt(A)为
F
w
t
(
A
)
=
{
(
F
w
t
(
A
0
+
A
1
)
,
F
w
t
(
A
0
−
A
1
)
)
n
>
1
A
n
=
1
Fwt(A) = \begin{cases} (Fwt(A_0+A_1),Fwt(A_0-A_1)) & n>1 \\ A & n=1 \end{cases}
Fwt(A)={(Fwt(A0+A1),Fwt(A0−A1))An>1n=1
性质1
F
w
t
(
A
+
B
)
=
F
w
t
(
A
)
+
F
w
t
(
B
)
Fwt(A+B)=Fwt(A)+Fwt(B)
Fwt(A+B)=Fwt(A)+Fwt(B)
证明:不难发现
F
w
t
(
A
)
Fwt(A)
Fwt(A)的每一项都是
A
A
A的一个线性组合,故满足加法分配律。
性质2
F
w
t
(
A
⊕
B
)
=
F
w
t
(
A
)
∗
F
w
t
(
B
)
Fwt(A\oplus B)=Fwt(A)*Fwt(B)
Fwt(A⊕B)=Fwt(A)∗Fwt(B)
证明:用数学归纳法来证。
当
n
=
1
n=1
n=1时显然成立。
当
n
>
1
n>1
n>1时有
F
w
t
(
A
⊕
B
)
Fwt(A\oplus B)
Fwt(A⊕B)
= F w t ( A 0 ⊕ B 0 + A 1 ⊕ B 1 , A 0 ⊕ B 1 + A 1 ⊕ B 0 ) =Fwt(A_0\oplus B_0+A_1\oplus B_1,A_0\oplus B_1+A_1\oplus B_0) =Fwt(A0⊕B0+A1⊕B1,A0⊕B1+A1⊕B0)
= ( F w t ( A 0 ⊕ B 0 + A 1 ⊕ B 1 + A 0 ⊕ B 1 + A 1 ⊕ B 0 ) , F w t ( A 0 ⊕ B 0 + A 1 ⊕ B 1 − A 0 ⊕ B 1 − A 1 ⊕ B 0 ) ) =(Fwt(A_0\oplus B_0+A_1\oplus B_1+A_0\oplus B_1+A_1\oplus B_0),Fwt(A_0\oplus B_0+A_1\oplus B_1-A_0\oplus B_1-A_1\oplus B_0)) =(Fwt(A0⊕B0+A1⊕B1+A0⊕B1+A1⊕B0),Fwt(A0⊕B0+A1⊕B1−A0⊕B1−A1⊕B0))
= ( F w t ( ( A 0 + A 1 ) ⊕ ( B 0 + B 1 ) ) , F w t ( ( A 0 − A 1 ) ⊕ ( B 0 − B 1 ) ) ) =(Fwt((A_0+A_1)\oplus (B_0+B_1)),Fwt((A_0-A_1)\oplus (B_0-B_1))) =(Fwt((A0+A1)⊕(B0+B1)),Fwt((A0−A1)⊕(B0−B1)))
= ( F w t ( A 0 + A 1 ) ∗ F w t ( B 0 + B 1 ) , F w t ( A 0 − A 1 ) ∗ F w t ( B 0 − B 1 ) ) =(Fwt(A_0+A_1)*Fwt(B_0+B_1),Fwt(A_0-A_1)*Fwt(B_0-B_1)) =(Fwt(A0+A1)∗Fwt(B0+B1),Fwt(A0−A1)∗Fwt(B0−B1))
= ( F w t ( A ) 0 ∗ F w t ( B ) 0 , F w t ( A ) 1 ∗ F w t ( B ) 1 ) =(Fwt(A)_0*Fwt(B)_0,Fwt(A)_1*Fwt(B)_1) =(Fwt(A)0∗Fwt(B)0,Fwt(A)1∗Fwt(B)1)
=
F
w
t
(
A
)
∗
F
w
t
(
B
)
=Fwt(A)*Fwt(B)
=Fwt(A)∗Fwt(B)
证毕。
逆变换
D w t ( F w t ( A ) ) Dwt(Fwt(A)) Dwt(Fwt(A))
= D w t ( F w t ( A 0 + A 1 ) , F w t ( A 0 − A 1 ) ) =Dwt(Fwt(A_0+A_1),Fwt(A_0-A_1)) =Dwt(Fwt(A0+A1),Fwt(A0−A1))
= D w t ( F w t ( A 0 ) + F w t ( A 1 ) , F w t ( A 0 ) − F w t ( A 1 ) ) =Dwt(Fwt(A_0)+Fwt(A_1),Fwt(A_0)-Fwt(A_1)) =Dwt(Fwt(A0)+Fwt(A1),Fwt(A0)−Fwt(A1))
令 D w t ( A ) = ( D w t ( A 0 + A 1 2 ) , D w t ( A 0 − A 1 2 ) ) Dwt(A)=(Dwt(\frac{A_0+A_1}{2}),Dwt(\frac{A_0-A_1}{2})) Dwt(A)=(Dwt(2A0+A1),Dwt(2A0−A1))
那么有 D w t ( F w t ( A ) ) Dwt(Fwt(A)) Dwt(Fwt(A))
= ( D w t ( F w t ( A 0 ) ) , D w t ( F w t ( A 1 ) ) ) =(Dwt(Fwt(A_0)),Dwt(Fwt(A_1))) =(Dwt(Fwt(A0)),Dwt(Fwt(A1)))
= ( A 0 , A 1 ) =(A_0,A_1) =(A0,A1)
求解
在求解
C
=
A
⊕
B
C=A\oplus B
C=A⊕B的时候,可以先对
A
A
A和
B
B
B分别做
F
w
t
Fwt
Fwt,得到
A
′
A'
A′和
B
′
B'
B′。
设
C
′
=
A
′
∗
B
′
C'=A'*B'
C′=A′∗B′,那么
C
=
D
w
t
(
C
′
)
C=Dwt(C')
C=Dwt(C′)。
时间复杂度
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)。
代码
void fwt(int *a,int l,int r)
{
if (l==r) return;
int n=(r-l+1)/2,mid=l+n-1;
fwt(a,l,mid);fwt(a,mid+1,r);
for (int i=l;i<=mid;i++)
{
int x=a[i],y=a[i+n];
a[i]=x+y;a[i+n]=x-y;
}
}
void dwt(int *a,int l,int r)
{
if (l==r) return;
int n=(r-l+1)/2,mid=l+n-1;
dwt(a,l,mid);dwt(a,mid+1,r);
for (int i=l;i<=mid;i++)
{
int x=a[i],y=a[i+n];
a[i]=(x+y)/2;a[i+n]=(x-y)/2;
}
}
AND
当
@
@
@为与运算的时候,通过上述方法不难验证
F
w
t
(
A
)
=
(
F
w
t
(
A
0
+
A
1
)
,
F
w
t
(
A
1
)
)
Fwt(A)=(Fwt(A_0+A_1),Fwt(A_1))
Fwt(A)=(Fwt(A0+A1),Fwt(A1))
D
w
t
(
A
)
=
(
D
w
t
(
A
0
−
A
1
)
,
F
w
t
(
A
1
)
)
Dwt(A)=(Dwt(A_0-A_1),Fwt(A_1))
Dwt(A)=(Dwt(A0−A1),Fwt(A1))
OR
当
@
@
@为或运算的时候,通过类比与运算不难验证
F
w
t
(
A
)
=
(
F
w
t
(
A
0
)
,
F
w
t
(
A
0
+
A
1
)
)
Fwt(A)=(Fwt(A_0),Fwt(A_0+A_1))
Fwt(A)=(Fwt(A0),Fwt(A0+A1))
D
w
t
(
A
)
=
(
D
w
t
(
A
0
)
,
D
w
t
(
A
1
−
A
0
)
)
Dwt(A)=(Dwt(A_0),Dwt(A_1-A_0))
Dwt(A)=(Dwt(A0),Dwt(A1−A0))