我们先速通一下前面的部分:
按位或
A=merge(A0,A0+A1)
a=merge(a0,a1−a0)
按位与
A=merge(A0+A1,A1)
a=merge(a0−a1,a1)
按位异或
A=merge(A0+A1,A0−A1)
a=merge(2a0+a1,2a0−a1)
我们设
c(i,j) 是
aj 对
Ai 的贡献系数。我们可以重新描述 FWT 变换的过程:
Ai=j=0∑n−1c(i,j)aj
因为有:
AiBi=Ci
所以我们可以通过简单的证明得到:
c(i,j)c(i,k)=c(i,j⊙k)。其中
⊙ 是任意一种位运算。
同时,
c 函数还有一个重要的性质,它可以按位处理。
举个例子,我们变换的时候:
Ai=j=0∑n−1c(i,j)aj
这么做是比较劣的,我们将其拆分:
Ai=j=0∑(n−1)/2c(i,j)aj+j=(n−1)/2+1∑n−1c(i,j)aj
考虑前面的式子和后面的式子
i,j 的区别,发现只有最高位不同。
所以我们将
i,j 去除最高位的值为
i′,j′,并记
i0 为
i 的最高位。有:
Ai=c(i0,0)j=0∑(n−1)/2c(i′,j′)aj+c(i0,1)j=(n−1)/2+1∑n−1c(i′,j′)aj
Ai=c(0,0)j=0∑(n−1)/2c(i′,j′)aj+c(0,1)j=(n−1)/2+1∑n−1c(i′,j′)aj
Ai=c(1,0)j=0∑(n−1)/2c(i′,j′)aj+c(1,1)j=(n−1)/2+1∑n−1c(i′,j′)aj
也就是说,我们只需要:
[c(0,0)c(1,0)c(0,1)c(1,1)]
四个数就可以完成变换了。我们称这个矩阵为位矩阵。
如果我们要进行逆变换,则需要上面的位矩阵的逆矩阵。
若逆矩阵为
c−1,可以通过类似操作得到原数:
ai=j=0∑nc−1(i,j)Aj
逆矩阵不一定存在,比如如果有一排
0 或者一列
0 那么这个矩阵就没有逆,我们在构造时需要格外小心。
按位或
我们可以构造:
[1101]
这样满足
c(i,j)c(i,k)=c(i,j∪k)。我们发现,这和我们前面推出的
A=merge(A0,A0+A1) 一模一样!同理,下面也是一个满足这个条件的矩阵,但我们一般使用上面这个:
[1110]
虽然下面这个矩阵也满足
c(i,j)c(i,k)=c(i,j∪k),但这个矩阵存在一排
0,不存在逆,所以不合法:
[0101]
如果我们要进行逆变换,则需要对矩阵求逆,以最上面这个矩阵为例,得:
[1−101]
然后按照顺变换的方法,把逆变换矩阵代入即可。
按位与
我们可以构造:
[1011]
这样满足
c(i,j)c(i,k)=c(i,j∩k)。
逆矩阵:
[10−11]
按位异或
我们可以构造:
[111−1]
这样满足
c(i,j)c(i,k)=c(i,j⊕k)。
逆矩阵:
[0.50.50.5−0.5]
K 维 FWT
其实位运算的本质是对一个
n 维
{0,1} 向量的运算。或运算就是每一维取
max。且运算就是每一维取
min。异或运算则是每一维对应相加再
mod2。
位运算有个特点:向量的每一位都是独立的。
我们把
{0,1} 扩展到
[0,K)∩Z 也就是扩展到
K 进制,看看会得到什么?
max 运算
我们将
∪ 运算拓展到
K 进制,定义
i∪j 表示按位取
max,有:
c(i,j)c(i,k)=c(i,j∪k)
c(i,j)c(i,j)=c(i,j)
也就是说,每一行的
1 必定只能在
0 的前面,如果在后面则不合法了。手玩一下可以发现一组合法构造:
1111011100110001
求逆可得:
1−10001−10001−10001
min 运算
我们将
∩ 运算拓展到
K 进制,定义
i∩j 表示按位取
min,有:
c(i,j)c(i,k)=c(i,j∩k)
c(i,j)c(i,j)=c(i,j)
也就是说,每一行的
1 必定只能在
0 的后面,如果在前面则不合法了。手玩一下可以发现一组合法构造:
1000110011101111
求逆可得:
1000−11000−11000−11
前两者用得比较少,用得比较多的是:
不进位加法
我们将
⊕ 运算拓展到
K 进制,定义
i⊕j 表示按位相加再
modK,有:
c(i,j)c(i,k)=c(i,j⊕k)
我们构造
c(i,j)=ωKj,就可以满足要求了:
ωKjωkk=ωK(j+k)modK
但是每一行都一样矩阵也没有逆,所以我们可以构造
c(i,j)=ωK(i−1)j 即可。
有下面这个矩阵:
1111⋮11ωK1ωK2ωK3⋮ωKk−11ωK2ωK4ωK6⋮ωK2(k−1)⋯⋯⋯⋯⋱⋯1ωKk−1ωK2(k−1)ωK3(k−1)⋮ωK(k−1)(k−1)
K11111⋮11ωK−1ωK−2ωK−3⋮ωK−(k−1)1ωK−2ωK−4ωK−6⋮ωK−2(k−1)⋯⋯⋯⋯⋱⋯1ωK−(k−1)ωK−2(k−1)ωK−3(k−1)⋮ωK−(k−1)(k−1)
如果我们题目给出的模数是存在单位根的,我们就可以简单实现。
但是
单位根在模意义下可能不存在,所以我们考虑扩域,就是人为地定义一个
x,满足
xK=1,然后直接把
x 代入计算,这样每个数都是一个关于
x 的
k−1 次多项式。我们只需要在
(modxK−1) 下计算即可。那么矩阵可以这么表示:
1111⋮11x1x2x3⋮xk−11x2x4x6⋮x2(k−1)⋯⋯⋯⋯⋱⋯1xk−1x2(k−1)x3(k−1)⋮x(k−1)(k−1)
但是这么做可能会存在零因子,也就是一个数有多种表示方法,我们无法确定一个数的真实值。
我们考虑不
(modxK−1) 了,我们
mod 分圆多项式
ΦK(x),他满足
x 的阶为
k,且在
Q 上不可约。所以我们定义上面的计算是在
(modΦK(x)) 下进行即可。
另一方面,如何求分圆多项式,这一点可以在
因式分解这道题的题解区里了解。这里给出分圆多项式的表:
还有一个问题是,
modΦK(x) 常数大(因为
Φ 本身就是一个多项式)。但是因为
ΦK(x)∣xk−1,我们只需要在计算时
modxk−1,最后再
modΦK(x) 即可。