FWT
快速沃尔什变换,在计算数学中,一个与阿达马变换有高度相关的快速沃尔什转换(fast Walsh–Hadamard transform,FWHTh)是一个十分有效率的算法,目的是计算阿达马变换。快速沃尔什转换是一个分而治之的算法,是一个常见的递回方法,将大小N的沃尔什转换拆成两个大小为N/2 的沃尔什转换。——百度百科
参考博客:
https://www.cnblogs.com/cjyyb/p/9065615.html
https://blog.csdn.net/zhouyuheng2003/article/details/84728063
首先,我们要弄明白我们为什么要用FWT,用它求什么。
对于
C
n
=
∑
i
+
j
=
n
A
i
∗
B
j
C
n
=
∑
i
∗
j
=
n
A
i
∗
B
j
C
n
=
∑
i
∣
j
=
n
A
i
∗
B
j
C
n
=
∑
i
&
j
=
n
A
i
∗
B
j
C
n
=
∑
i
⊕
j
=
n
A
i
∗
B
j
\begin{aligned} C_n&=\sum_{i+j=n}A_i*B_j\\ C_n&=\sum_{i*j=n}A_i*B_j\\ C_n&=\sum_{i|j=n}A_i*B_j\\ C_n&=\sum_{i\&j=n}A_i*B_j\\ C_n&=\sum_{i\oplus j=n}A_i*B_j\\ \end{aligned}
CnCnCnCnCn=i+j=n∑Ai∗Bj=i∗j=n∑Ai∗Bj=i∣j=n∑Ai∗Bj=i&j=n∑Ai∗Bj=i⊕j=n∑Ai∗Bj
对于这几个公式,第一个的
i
+
j
=
n
i+j=n
i+j=n是可以使用FFT来求取的,第二个的
i
∗
j
=
n
i*j=n
i∗j=n的特殊情况下也是可以使用FFT的。但是后面三个是无法使用FFT的。所以也就有了FWT
定义:
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
)
\begin{aligned} A-B&=(a_0-b_0,a_1-b_1,\cdots,a_{n-1}-b_{n-1})\\ A+B&=(a_0+b_0,a_1+b_1,\cdots,a_{n-1}+b_{n-1})\\ A*B&=(a_0*b_0,a_1*b_1,\cdots,a_{n-1}*b_{n-1})\\ A@B&=(\sum_{i@j=0}a_i*b_j,\sum_{i@j=1}a_i*b_j,\cdots,\sum_{i@j=n-1}a_i*b_j) \end{aligned}
A−BA+BA∗BA@B=(a0−b0,a1−b1,⋯,an−1−bn−1)=(a0+b0,a1+b1,⋯,an−1+bn−1)=(a0∗b0,a1∗b1,⋯,an−1∗bn−1)=(i@j=0∑ai∗bj,i@j=1∑ai∗bj,⋯,i@j=n−1∑ai∗bj)
其中
@
@
@属于集合
{
∣
(
或
)
,
&
(
与
)
,
∧
(
异
或
)
}
\{ |(或),\&(与), \wedge(异或) \}
{∣(或),&(与),∧(异或)}
并且
@
@
@运算具有分配率
A
@
(
B
+
C
)
=
A
@
B
+
A
@
C
A@(B+C)=A@B+A@C
A@(B+C)=A@B+A@C也具有交换律
A
∣
B
=
B
∣
A
A|B=B|A
A∣B=B∣A
另外定义
A
0
A_0
A0为多项式
A
A
A(A有
2
n
2^n
2n项)的前
2
n
−
1
2^{n-1}
2n−1项,
A
1
A_1
A1为多项式
A
A
A的后
2
n
−
1
2^{n-1}
2n−1项
A
=
(
A
0
,
A
1
)
A=(A_0,A_1)
A=(A0,A1)表示多项式
A
0
A_0
A0后面加上
A
1
A_1
A1多项式形成多项式
A
A
A
思路
和FFT一样,先进行FWT求出两个多项式的
F
W
T
(
A
)
,
F
W
T
(
B
)
FWT(A),FWT(B)
FWT(A),FWT(B),然后对应相乘得到
F
W
T
(
C
)
FWT(C)
FWT(C),最后逆运算IFWT得到答案多项式C
1.OR 或卷积
c
k
=
∑
i
∣
j
=
k
a
i
∗
b
j
C
=
A
∣
B
=
(
∑
i
∣
j
=
0
a
i
∗
b
j
,
∑
i
∣
j
=
1
a
i
∗
b
j
,
⋯
 
,
∑
i
∣
j
=
n
−
1
a
i
∗
b
j
)
\begin{aligned} c_k&=\sum_{i|j=k}a_i*b_j\\ C=A|B&=(\sum_{i|j=0}a_i*b_j,\sum_{i|j=1}a_i*b_j,\cdots,\sum_{i|j=n-1}a_i*b_j)\\ \end{aligned}
ckC=A∣B=i∣j=k∑ai∗bj=(i∣j=0∑ai∗bj,i∣j=1∑ai∗bj,⋯,i∣j=n−1∑ai∗bj)
正变换
F
W
T
(
A
)
=
{
(
F
W
T
(
A
0
)
,
F
W
T
(
A
0
+
A
1
)
)
n>0
A
n=0
FWT(A)=\begin{cases} (FWT(A_0),FWT(A_0+A_1))&\text{n>0}\\ A&\text{n=0} \end{cases}
FWT(A)={(FWT(A0),FWT(A0+A1))An>0n=0
对应项相乘
F
W
T
(
C
)
=
F
W
T
(
A
)
∗
F
W
T
(
B
)
FWT(C)=FWT(A)*FWT(B)
FWT(C)=FWT(A)∗FWT(B)
逆变换
I
F
W
T
(
A
)
=
{
(
I
F
W
T
(
A
0
)
,
I
F
W
T
(
A
1
)
−
I
F
W
T
(
A
0
)
)
n>0
A
n=0
IFWT(A)=\begin{cases} (IFWT(A_0),IFWT(A_1)-IFWT(A_0))&\text{n>0}\\ A&\text{n=0} \end{cases}
IFWT(A)={(IFWT(A0),IFWT(A1)−IFWT(A0))An>0n=0
2.AND 与卷积
c
k
=
∑
i
&
j
=
k
a
i
∗
b
j
C
=
A
&
B
=
(
∑
i
&
j
=
0
a
i
∗
b
j
,
∑
i
&
j
=
1
a
i
∗
b
j
,
⋯
 
,
∑
i
&
j
=
n
−
1
a
i
∗
b
j
)
\begin{aligned} c_k&=\sum_{i\&j=k}a_i*b_j\\ C=A\&B&=(\sum_{i\&j=0}a_i*b_j,\sum_{i\&j=1}a_i*b_j,\cdots,\sum_{i\&j=n-1}a_i*b_j)\\ \end{aligned}
ckC=A&B=i&j=k∑ai∗bj=(i&j=0∑ai∗bj,i&j=1∑ai∗bj,⋯,i&j=n−1∑ai∗bj)
正变换
F
W
T
(
A
)
=
{
(
F
W
T
(
A
0
+
A
1
)
,
F
W
T
(
A
1
)
)
n>0
A
n=0
FWT(A)=\begin{cases} (FWT(A_0+A_1),FWT(A_1))&\text{n>0}\\ A&\text{n=0} \end{cases}
FWT(A)={(FWT(A0+A1),FWT(A1))An>0n=0
对应项相乘
F
W
T
(
C
)
=
F
W
T
(
A
)
∗
F
W
T
(
B
)
FWT(C)=FWT(A)*FWT(B)
FWT(C)=FWT(A)∗FWT(B)
逆变换
I
F
W
T
(
A
)
=
{
(
I
F
W
T
(
A
0
)
−
I
F
W
T
(
A
1
)
,
I
F
W
T
(
A
0
)
)
n>0
A
n=0
IFWT(A)=\begin{cases} (IFWT(A_0)-IFWT(A_1),IFWT(A_0))&\text{n>0}\\ A&\text{n=0} \end{cases}
IFWT(A)={(IFWT(A0)−IFWT(A1),IFWT(A0))An>0n=0
3.XOR 异或卷积
c
k
=
∑
i
⊕
j
=
k
a
i
∗
b
j
C
=
A
⊕
B
=
(
∑
i
⊕
j
=
0
a
i
∗
b
j
,
∑
i
⊕
j
=
1
a
i
∗
b
j
,
⋯
 
,
∑
i
⊕
j
=
n
−
1
a
i
∗
b
j
)
\begin{aligned} c_k&=\sum_{i\oplus j=k}a_i*b_j\\ C=A\oplus B&=(\sum_{i\oplus j=0}a_i*b_j,\sum_{i\oplus j=1}a_i*b_j,\cdots,\sum_{i\oplus j=n-1}a_i*b_j)\\ \end{aligned}
ckC=A⊕B=i⊕j=k∑ai∗bj=(i⊕j=0∑ai∗bj,i⊕j=1∑ai∗bj,⋯,i⊕j=n−1∑ai∗bj)
正变换
F
W
T
(
A
)
=
{
(
F
W
T
(
A
0
+
A
1
)
,
F
W
T
(
A
0
−
A
1
)
)
n>0
A
n=0
FWT(A)=\begin{cases} (FWT(A_0+A_1),FWT(A_0-A_1))&\text{n>0}\\ A&\text{n=0} \end{cases}
FWT(A)={(FWT(A0+A1),FWT(A0−A1))An>0n=0
对应项相乘
F
W
T
(
C
)
=
F
W
T
(
A
)
∗
F
W
T
(
B
)
FWT(C)=FWT(A)*FWT(B)
FWT(C)=FWT(A)∗FWT(B)
逆变换
I
F
W
T
(
A
)
=
{
(
I
F
W
T
(
A
0
)
+
I
F
W
T
(
A
1
)
2
,
I
F
W
T
(
A
0
)
−
I
F
W
T
(
A
1
)
2
)
n>0
A
n=0
IFWT(A)=\begin{cases} (\cfrac{IFWT(A_0)+IFWT(A_1)}{2},\cfrac{IFWT(A_0)-IFWT(A_1)}{2})&\text{n>0}\\ A&\text{n=0} \end{cases}
IFWT(A)=⎩⎨⎧(2IFWT(A0)+IFWT(A1),2IFWT(A0)−IFWT(A1))An>0n=0
代码
/*
*opt = 1 正变换
*opt = -1 逆变换
*/
void FWT_or(int *a,int opt,int N){
for(int i = 1; i < N; i <<= 1){
for(int p = i<<1,j = 0; j < N; j += p){
for(int k = 0; k < i; ++k){
int x = a[j+k],y = a[i+j+k];
if(opt == 1) a[i+j+k] = (x+y)%MOD;
else a[i+j+k] = (y-x+MOD)%MOD;
}
}
}
}
void FWT_and(int *a,int opt,int N){
for(int i = 1; i < N; i <<= 1){
for(int p = i<<1, j = 0; j < N; j += p){
for(int k = 0; k < i; ++k){
int x = a[j+k],y = a[i+j+k];
if(opt == 1) a[i+j+k] = (x+y)%MOD;
else a[i+j+k] = (x-y+MOD)%MOD;
}
}
}
}
void FWT_xor(int *a,int opt,int N){
for(int i = 1; i < N; i <<= 1){
for(int p = i<<1,j = 0; j < N; j += p){
for(int k = 0; k < i; ++k){
int x = a[j+k],y = a[i+j+k];
a[j+k] = (x+y)%MOD;
a[i+j+k] = (x-y+MOD)%MOD;
//inv2表示2在模mod下的逆元,如果不是在模意义下的话,开一个long long,然后把乘逆元变成直接除二
if(opt == -1) a[j+k] = 1LL*a[j+k]*inv2%MOD,a[i+j+k] = 1LL*a[i+j+k]*inv2%MOD;
}
}
}
}