1前言
在之前学完了FFT稍微码了一些题、也学习了一下NTT相关的知识之后,我觉得有必要学习一下FWT,这篇博客就是阐述我对FWT的理解的
2介绍
2.1解决的问题
对于FFT,它的过程本质上是
c
n
=
∑
i
+
j
=
n
a
i
∗
b
j
c_n=\sum_{i+j=n}a_i*b_j
cn=i+j=n∑ai∗bj
然后考虑一下那个
i
+
j
=
n
i+j=n
i+j=n的情况,如果换个符号,比如
i
−
j
=
n
i-j=n
i−j=n,那么想必你也会做,只要把B翻转就好了
在NTT的题中,其实
i
∗
j
=
n
(
m
o
d
p
)
i*j=n\pmod p
i∗j=n(modp),在p有原根的时候也可以做,直接把i位置的数换到
log
原
根
i
\log_{原根}i
log原根i,然后再做NTT,最后弄回来就好了(update:对怎么样的数有原根、对原根的性质有不理解的可以看我的博客原根哦)
那么对于
i
∣
j
=
n
i|j=n
i∣j=n、
i
&
j
=
n
i\& j=n
i&j=n、
i
⊕
j
=
n
i\oplus j=n
i⊕j=n的情况怎么办?
可以用FWT来解决
这篇文章中用到的只是快速沃尔什变换(FWT)的一个特殊情况,有兴趣可以去网上搜一搜广义的快速沃尔什是干什么的
2.2文章中有可能用到的符号&特殊说明
首先,这篇博客中提到的n(多项式的项数)如无特殊说明都是2的幂次,方便处理,如果不为2的幂次,可以在高次加0系数
然后,对于一些公式,你可能会觉得比较长,其实只是因为我列的项数比较多导致的,你可以只看第一项来看懂我在推什么
对于一个一般的多项式
f
(
x
)
=
a
0
x
0
+
a
1
x
1
+
⋅
⋅
⋅
+
a
n
−
1
x
n
−
1
f(x)=a_0x^0+a_1x^1+···+a_{n-1}x^{n-1}
f(x)=a0x0+a1x1+⋅⋅⋅+an−1xn−1
将其表示为
(
a
0
,
a
1
,
a
2
⋅
⋅
⋅
a
n
−
1
)
(a_0,a_1,a_2···a_{n-1})
(a0,a1,a2⋅⋅⋅an−1)
定义多项式加法
C
(
x
)
=
A
(
x
)
+
B
(
x
)
=
(
a
0
,
a
1
,
a
2
⋅
⋅
⋅
a
n
−
1
)
+
(
b
0
,
b
1
,
b
2
⋅
⋅
⋅
b
n
−
1
)
=
(
a
0
+
b
0
,
a
1
+
b
1
,
a
2
+
b
2
⋅
⋅
⋅
a
n
−
1
+
b
n
−
1
)
\begin{aligned} C(x)&=A(x)+B(x)\\ &=(a_0,a_1,a_2···a_{n-1})+(b_0,b_1,b_2···b_{n-1})\\ &=(a_0+b_0,a_1+b_1,a_2+b_2···a_{n-1}+b_{n-1})\\ \end{aligned}
C(x)=A(x)+B(x)=(a0,a1,a2⋅⋅⋅an−1)+(b0,b1,b2⋅⋅⋅bn−1)=(a0+b0,a1+b1,a2+b2⋅⋅⋅an−1+bn−1)
多项式的减法把符号变成减号
C
(
x
)
=
A
(
x
)
−
B
(
x
)
=
(
a
0
,
a
1
,
a
2
⋅
⋅
⋅
a
n
−
1
)
−
(
b
0
,
b
1
,
b
2
⋅
⋅
⋅
b
n
−
1
)
=
(
a
0
−
b
0
,
a
1
−
b
1
,
a
2
−
b
2
⋅
⋅
⋅
a
n
−
1
−
b
n
−
1
)
\begin{aligned} C(x)&=A(x)-B(x)\\ &=(a_0,a_1,a_2···a_{n-1})-(b_0,b_1,b_2···b_{n-1})\\ &=(a_0-b_0,a_1-b_1,a_2-b_2···a_{n-1}-b_{n-1})\\ \end{aligned}
C(x)=A(x)−B(x)=(a0,a1,a2⋅⋅⋅an−1)−(b0,b1,b2⋅⋅⋅bn−1)=(a0−b0,a1−b1,a2−b2⋅⋅⋅an−1−bn−1)
多项式的对应系数相乘乘法(区别于那个FFT做的卷积的乘法)
C
(
x
)
=
A
(
x
)
∗
B
(
x
)
=
(
a
0
,
a
1
,
a
2
⋅
⋅
⋅
a
n
−
1
)
∗
(
b
0
,
b
1
,
b
2
⋅
⋅
⋅
b
n
−
1
)
=
(
a
0
∗
b
0
,
a
1
∗
b
1
,
a
2
∗
b
2
⋅
⋅
⋅
a
n
−
1
∗
b
n
−
1
)
\begin{aligned} C(x)&=A(x)*B(x)\\ &=(a_0,a_1,a_2···a_{n-1})*(b_0,b_1,b_2···b_{n-1})\\ &=(a_0*b_0,a_1*b_1,a_2*b_2···a_{n-1}*b_{n-1})\\ \end{aligned}
C(x)=A(x)∗B(x)=(a0,a1,a2⋅⋅⋅an−1)∗(b0,b1,b2⋅⋅⋅bn−1)=(a0∗b0,a1∗b1,a2∗b2⋅⋅⋅an−1∗bn−1)
对于多项式的一个操作
@
(
@
∈
{
∣
(
或
)
,
&
(
与
)
,
⊕
(
异
或
)
}
)
@(@ \in \left\{ |(或),\&(与),\oplus(异或) \right\})
@(@∈{∣(或),&(与),⊕(异或)}),请看清楚,这里的是卷积,FFT做的多项式乘法相当于这里的符号用“+”,然而多项式的“+”已经被定义过了,前面的系数相乘乘法事实上不应该用那个符号,所以没有列出
C
(
x
)
=
A
(
x
)
@
B
(
x
)
=
(
a
0
,
a
1
,
a
2
⋅
⋅
⋅
a
n
−
1
)
@
(
b
0
,
b
1
,
b
2
⋅
⋅
⋅
b
n
−
1
)
=
(
∑
i
@
j
=
0
a
i
∗
b
j
,
∑
i
@
j
=
1
a
i
∗
b
j
,
∑
i
@
j
=
2
a
i
∗
b
j
⋅
⋅
⋅
∑
i
@
j
=
n
−
1
a
i
∗
b
j
)
\begin{aligned} C(x)&=A(x)@B(x)\\ &=(a_0,a_1,a_2···a_{n-1})@(b_0,b_1,b_2···b_{n-1})\\ &=(\sum _{i@j=0}a_i*b_j,\sum _{i@j=1}a_i*b_j,\sum _{i@j=2}a_i*b_j···\sum _{i@j=n-1}a_i*b_j)\\ \end{aligned}
C(x)=A(x)@B(x)=(a0,a1,a2⋅⋅⋅an−1)@(b0,b1,b2⋅⋅⋅bn−1)=(i@j=0∑ai∗bj,i@j=1∑ai∗bj,i@j=2∑ai∗bj⋅⋅⋅i@j=n−1∑ai∗bj)
特殊的,这里的
@
@
@运算具有分配律,即
(
A
+
B
)
@
C
=
A
@
C
+
B
@
C
(A+B)@C=A@C+B@C
(A+B)@C=A@C+B@C,至于证明也非常方便:
∑
i
@
j
=
x
(
a
i
+
b
i
)
∗
c
j
=
∑
i
@
j
=
x
(
a
i
∗
c
j
+
b
i
∗
c
j
)
=
∑
i
@
j
=
x
a
i
∗
c
j
+
∑
i
@
j
=
x
b
i
∗
c
j
\begin{aligned} \sum _{i@j=x}(a_i+b_i)*c_j&=\sum _{i@j=x}(a_i*c_j+b_i*c_j)\\ &=\sum _{i@j=x}a_i*c_j+\sum _{i@j=x}b_i*c_j \end{aligned}
i@j=x∑(ai+bi)∗cj=i@j=x∑(ai∗cj+bi∗cj)=i@j=x∑ai∗cj+i@j=x∑bi∗cj
另外对于一个多项式
A
A
A,设
n
=
2
k
n=2^k
n=2k,定义
A
0
A_0
A0为
A
A
A的前
2
k
−
1
2^{k-1}
2k−1个系数、定义
A
1
A_1
A1为
A
A
A的后
2
k
−
1
2^{k-1}
2k−1个系数
定义运算
A
=
(
B
,
C
)
A=(B,C)
A=(B,C)表示B这个多项式后面接上C等于A
用字母表示大概意思是:
(
A
,
B
)
=
(
(
a
0
,
a
1
,
a
2
⋅
⋅
⋅
a
x
−
1
)
,
(
b
0
,
b
1
,
b
2
⋅
⋅
⋅
b
y
−
1
)
)
=
(
a
0
,
a
1
,
a
2
⋅
⋅
⋅
a
x
−
1
,
b
0
,
b
1
,
b
2
⋅
⋅
⋅
b
y
−
1
)
\begin{aligned} (A,B)&=((a_0,a_1,a_2···a_{x-1}),(b_0,b_1,b_2···b_{y-1}))\\ &=(a_0,a_1,a_2···a_{x-1},b_0,b_1,b_2···b_{y-1})\\ \end{aligned}
(A,B)=((a0,a1,a2⋅⋅⋅ax−1),(b0,b1,b2⋅⋅⋅by−1))=(a0,a1,a2⋅⋅⋅ax−1,b0,b1,b2⋅⋅⋅by−1)
2.3FWT的大致思路
假设我们现在有两个多项式 A A A、 B B B以及一个位运算符 @ @ @,思路和FFT相似,先求出某个多项式 F W T ( A ) FWT(A) FWT(A)和 F W T ( B ) FWT(B) FWT(B),然后对应相乘得到多项式 F W T ( C ) FWT(C) FWT(C),最后进行 I F W T IFWT IFWT,得出结果 C C C
3实现
update:这里的前两个(and/or)更严格意义上来说是FMT,本篇博客提供FMT本身的相关内容,另一篇博客提供FMT的更多小应用
3.1or运算(本质FMT)
3.1.1构造
先来讲or运算吧
现在要求的是:
c
n
=
∑
i
∣
j
=
n
a
i
b
j
c_n=\sum_{i|j=n}a_ib_j
cn=i∣j=n∑aibj
定义FWT(A):
F
W
T
(
A
)
=
(
∑
i
∣
0
=
0
a
i
,
∑
i
∣
1
=
1
a
i
,
∑
i
∣
2
=
2
a
i
⋅
⋅
⋅
∑
i
∣
(
n
−
1
)
=
(
n
−
1
)
a
i
)
\begin{aligned} FWT(A)=(\sum_{i|0=0}a_i,\sum_{i|1=1}a_i,\sum_{i|2=2}a_i···\sum_{i|(n-1)=(n-1)}a_i) \end{aligned}
FWT(A)=(i∣0=0∑ai,i∣1=1∑ai,i∣2=2∑ai⋅⋅⋅i∣(n−1)=(n−1)∑ai)
容易发现一件事:
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
)
∗
F
W
T
(
B
)
=
(
∑
i
∣
0
=
0
a
i
,
∑
i
∣
1
=
1
a
i
,
∑
i
∣
2
=
2
a
i
⋅
⋅
⋅
∑
i
∣
(
n
−
1
)
=
(
n
−
1
)
a
i
)
∗
(
∑
i
∣
0
=
0
b
i
,
∑
i
∣
1
=
1
b
i
,
∑
i
∣
2
=
2
b
i
⋅
⋅
⋅
∑
i
∣
(
n
−
1
)
=
(
n
−
1
)
b
i
)
=
(
(
∑
i
∣
0
=
0
a
i
)
∗
(
∑
j
∣
0
=
0
b
j
)
,
(
∑
i
∣
1
=
1
a
i
)
∗
(
∑
j
∣
1
=
1
b
j
)
,
(
∑
i
∣
2
=
2
a
i
)
∗
(
∑
j
∣
2
=
2
b
j
)
⋅
⋅
⋅
(
∑
i
∣
(
n
−
1
)
=
(
n
−
1
)
a
i
)
∗
(
∑
j
∣
(
n
−
1
)
=
(
n
−
1
)
b
j
)
)
=
(
∑
i
∣
j
∣
0
=
0
a
i
∗
b
j
,
∑
i
∣
j
∣
1
=
1
a
i
∗
b
j
,
∑
i
∣
j
∣
2
=
2
a
i
∗
b
j
⋅
⋅
⋅
∑
i
∣
j
∣
(
n
−
1
)
=
(
n
−
1
)
a
i
∗
b
j
)
=
(
∑
k
∣
0
=
0
∑
i
∣
j
=
k
a
i
∗
b
j
,
∑
k
∣
1
=
1
∑
i
∣
j
=
k
a
i
∗
b
j
,
∑
k
∣
2
=
2
∑
i
∣
j
=
k
a
i
∗
b
j
⋅
⋅
⋅
∑
k
∣
(
n
−
1
)
=
(
n
−
1
)
∑
i
∣
j
=
k
a
i
∗
b
j
)
=
F
W
T
(
A
∣
B
)
\begin{aligned} FWT(A)*FWT(B)&=(\sum_{i|0=0}a_i,\sum_{i|1=1}a_i,\sum_{i|2=2}a_i···\sum_{i|(n-1)=(n-1)}a_i)*(\sum_{i|0=0}b_i,\sum_{i|1=1}b_i,\sum_{i|2=2}b_i···\sum_{i|(n-1)=(n-1)}b_i)\\ &=((\sum_{i|0=0}a_i)*(\sum_{j|0=0}b_j),(\sum_{i|1=1}a_i)*(\sum_{j|1=1}b_j),(\sum_{i|2=2}a_i)*(\sum_{j|2=2}b_j)···(\sum_{i|(n-1)=(n-1)}a_i)*(\sum_{j|(n-1)=(n-1)}b_j))\\ &=(\sum_{i|j|0=0}a_i*b_j,\sum_{i|j|1=1}a_i*b_j,\sum_{i|j|2=2}a_i*b_j···\sum_{i|j|(n-1)=(n-1)}a_i*b_j)\\ &=(\sum_{k|0=0}\sum_{i|j=k}a_i*b_j,\sum_{k|1=1}\sum_{i|j=k}a_i*b_j,\sum_{k|2=2}\sum_{i|j=k}a_i*b_j···\sum_{k|(n-1)=(n-1)}\sum_{i|j=k}a_i*b_j)\\ &=FWT(A|B) \end{aligned}
FWT(A)∗FWT(B)=(i∣0=0∑ai,i∣1=1∑ai,i∣2=2∑ai⋅⋅⋅i∣(n−1)=(n−1)∑ai)∗(i∣0=0∑bi,i∣1=1∑bi,i∣2=2∑bi⋅⋅⋅i∣(n−1)=(n−1)∑bi)=((i∣0=0∑ai)∗(j∣0=0∑bj),(i∣1=1∑ai)∗(j∣1=1∑bj),(i∣2=2∑ai)∗(j∣2=2∑bj)⋅⋅⋅(i∣(n−1)=(n−1)∑ai)∗(j∣(n−1)=(n−1)∑bj))=(i∣j∣0=0∑ai∗bj,i∣j∣1=1∑ai∗bj,i∣j∣2=2∑ai∗bj⋅⋅⋅i∣j∣(n−1)=(n−1)∑ai∗bj)=(k∣0=0∑i∣j=k∑ai∗bj,k∣1=1∑i∣j=k∑ai∗bj,k∣2=2∑i∣j=k∑ai∗bj⋅⋅⋅k∣(n−1)=(n−1)∑i∣j=k∑ai∗bj)=FWT(A∣B)
当然这个的证明还有其它的很多方法,我觉得我的这个证明还是比较清楚的
也就是说,现在:
- 问题一:
已知一个多项式A,求FWT(A)
即FWT - 问题二:
已知FWT(A),求A
即IFWT
解决这两个问题,我们就能够:
- 已知A,B
- FWT,求出FWT(A),FWT(B)
- 对应系数相乘,求出FWT(A|B)
- IFWT,求出A|B
3.1.2计算
我们可以递归定义
F
W
T
(
A
)
=
{
(
F
W
T
(
A
0
)
,
F
W
T
(
A
0
+
A
1
)
)
(
n
≠
1
)
A
(
n
=
1
)
FWT(A)=\begin{cases} (FWT(A_0),FWT(A_0+A_1))(n\ne1)\\ A(n=1) \end{cases}
FWT(A)={(FWT(A0),FWT(A0+A1))(n̸=1)A(n=1)
这么定义的原因:因为
A
0
A_0
A0的编号的最高位都是0,
A
1
A_1
A1的编号与
A
0
A_0
A0的编号的最高位变成1的结果一一对应,因为是or运算,所以
A
0
A_0
A0能到
A
1
A_1
A1里一一对应的贡献
然后考虑
I
F
W
T
IFWT
IFWT(定义
I
F
W
T
(
F
W
T
(
A
)
)
=
A
IFWT(FWT(A))=A
IFWT(FWT(A))=A),由于
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)(这个证明不用说了吧,看我的定义,这个相当于乘法分配律拆一下就好了),可以列出
I
F
W
T
IFWT
IFWT的式子,推导:
已知
F
W
T
(
A
)
0
FWT(A)_0
FWT(A)0、
F
W
T
(
A
)
1
FWT(A)_1
FWT(A)1,求
A
0
A_0
A0、
A
1
A_1
A1
∵
F
W
T
(
A
)
0
=
F
W
T
(
A
0
)
∴
A
0
=
I
D
F
T
(
F
W
T
(
A
0
)
)
=
I
D
F
T
(
F
W
T
(
A
)
0
)
∵
F
W
T
(
A
)
1
=
F
W
T
(
A
0
)
+
F
W
T
(
A
1
)
∴
A
1
=
I
D
F
T
(
F
W
T
(
A
1
)
)
=
I
D
F
T
(
F
W
T
(
A
)
1
−
F
W
T
(
A
)
0
)
\because FWT(A)_0=FWT(A_0)\\ \therefore A_0=IDFT(FWT(A_0))=IDFT(FWT(A)_0)\\ \because FWT(A)_1=FWT(A_0)+FWT(A_1)\\ \therefore A_1= IDFT(FWT(A_1))=IDFT(FWT(A)_1-FWT(A)_0)
∵FWT(A)0=FWT(A0)∴A0=IDFT(FWT(A0))=IDFT(FWT(A)0)∵FWT(A)1=FWT(A0)+FWT(A1)∴A1=IDFT(FWT(A1))=IDFT(FWT(A)1−FWT(A)0)
总结:
I
F
W
T
(
A
)
=
{
(
I
F
W
T
(
A
0
)
,
I
F
W
T
(
A
1
−
A
0
)
)
(
n
≠
1
)
A
(
n
=
1
)
IFWT(A)=\begin{cases} (IFWT(A_0),IFWT(A_1-A_0))(n\ne1)\\ A(n=1) \end{cases}
IFWT(A)={(IFWT(A0),IFWT(A1−A0))(n̸=1)A(n=1)
然后就可以写代码了(代码和FFT有点像)
inline void FWT(LL*A,const int fla)
{
for(rg int i=1;i<lenth;i<<=1)
for(rg int j=0;j<lenth;j+=(i<<1))
for(rg int k=0;k<i;k++)
A[j+k+i]+=A[j+k]*fla;
}
然后or运算的FWT就没了
3.2and运算(本质FMT)
3.2.1构造
and其实和or差的不多
现在要求的是:
c
n
=
∑
i
&
j
=
n
a
i
b
j
c_n=\sum_{i\&j=n}a_ib_j
cn=i&j=n∑aibj
同样定义FWT(A):
F
W
T
(
A
)
=
(
∑
i
&
0
=
0
a
i
,
∑
i
&
1
=
1
a
i
,
∑
i
&
2
=
2
a
i
⋅
⋅
⋅
∑
i
&
(
n
−
1
)
=
(
n
−
1
)
a
i
)
\begin{aligned} FWT(A)=(\sum_{i\&0=0}a_i,\sum_{i\&1=1}a_i,\sum_{i\&2=2}a_i···\sum_{i\&(n-1)=(n-1)}a_i) \end{aligned}
FWT(A)=(i&0=0∑ai,i&1=1∑ai,i&2=2∑ai⋅⋅⋅i&(n−1)=(n−1)∑ai)
同样的:
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
)
∗
F
W
T
(
B
)
=
(
∑
i
&
0
=
0
a
i
,
∑
i
&
1
=
1
a
i
,
∑
i
&
2
=
2
a
i
⋅
⋅
⋅
∑
i
&
(
n
−
1
)
=
(
n
−
1
)
a
i
)
∗
(
∑
i
&
0
=
0
b
i
,
∑
i
&
1
=
1
b
i
,
∑
i
&
2
=
2
b
i
⋅
⋅
⋅
∑
i
&
(
n
−
1
)
=
(
n
−
1
)
b
i
)
=
(
(
∑
i
&
0
=
0
a
i
)
∗
(
∑
j
&
0
=
0
b
j
)
,
(
∑
i
&
1
=
1
a
i
)
∗
(
∑
j
&
1
=
1
b
j
)
,
(
∑
i
&
2
=
2
a
i
)
∗
(
∑
j
&
2
=
2
b
j
)
⋅
⋅
⋅
(
∑
i
&
(
n
−
1
)
=
(
n
−
1
)
a
i
)
∗
(
∑
j
&
(
n
−
1
)
=
(
n
−
1
)
b
j
)
)
=
(
∑
i
&
j
&
0
=
0
a
i
∗
b
j
,
∑
i
&
j
&
1
=
1
a
i
∗
b
j
,
∑
i
&
j
&
2
=
2
a
i
∗
b
j
⋅
⋅
⋅
∑
i
&
j
&
(
n
−
1
)
=
(
n
−
1
)
a
i
∗
b
j
)
=
(
∑
k
&
0
=
0
∑
i
&
j
=
k
a
i
∗
b
j
,
∑
k
&
1
=
1
∑
i
&
j
=
k
a
i
∗
b
j
,
∑
k
&
2
=
2
∑
i
&
j
=
k
a
i
∗
b
j
⋅
⋅
⋅
∑
k
&
(
n
−
1
)
=
(
n
−
1
)
∑
i
&
j
=
k
a
i
∗
b
j
)
=
F
W
T
(
A
&
B
)
\begin{aligned} FWT(A)*FWT(B)&=(\sum_{i\&0=0}a_i,\sum_{i\&1=1}a_i,\sum_{i\&2=2}a_i···\sum_{i\&(n-1)=(n-1)}a_i)*(\sum_{i\&0=0}b_i,\sum_{i\&1=1}b_i,\sum_{i\&2=2}b_i···\sum_{i\&(n-1)=(n-1)}b_i)\\ &=((\sum_{i\&0=0}a_i)*(\sum_{j\&0=0}b_j),(\sum_{i\&1=1}a_i)*(\sum_{j\&1=1}b_j),(\sum_{i\&2=2}a_i)*(\sum_{j\&2=2}b_j)···(\sum_{i\&(n-1)=(n-1)}a_i)*(\sum_{j\&(n-1)=(n-1)}b_j))\\ &=(\sum_{i\&j\&0=0}a_i*b_j,\sum_{i\&j\&1=1}a_i*b_j,\sum_{i\&j\&2=2}a_i*b_j···\sum_{i\&j\&(n-1)=(n-1)}a_i*b_j)\\ &=(\sum_{k\&0=0}\sum_{i\&j=k}a_i*b_j,\sum_{k\&1=1}\sum_{i\&j=k}a_i*b_j,\sum_{k\&2=2}\sum_{i\&j=k}a_i*b_j···\sum_{k\&(n-1)=(n-1)}\sum_{i\&j=k}a_i*b_j)\\ &=FWT(A\&B) \end{aligned}
FWT(A)∗FWT(B)=(i&0=0∑ai,i&1=1∑ai,i&2=2∑ai⋅⋅⋅i&(n−1)=(n−1)∑ai)∗(i&0=0∑bi,i&1=1∑bi,i&2=2∑bi⋅⋅⋅i&(n−1)=(n−1)∑bi)=((i&0=0∑ai)∗(j&0=0∑bj),(i&1=1∑ai)∗(j&1=1∑bj),(i&2=2∑ai)∗(j&2=2∑bj)⋅⋅⋅(i&(n−1)=(n−1)∑ai)∗(j&(n−1)=(n−1)∑bj))=(i&j&0=0∑ai∗bj,i&j&1=1∑ai∗bj,i&j&2=2∑ai∗bj⋅⋅⋅i&j&(n−1)=(n−1)∑ai∗bj)=(k&0=0∑i&j=k∑ai∗bj,k&1=1∑i&j=k∑ai∗bj,k&2=2∑i&j=k∑ai∗bj⋅⋅⋅k&(n−1)=(n−1)∑i&j=k∑ai∗bj)=FWT(A&B)
然后没啦
3.2.2计算
我们一样可以递归定义
F
W
T
(
A
)
=
{
(
F
W
T
(
A
0
+
A
1
)
,
F
W
T
(
A
1
)
)
(
n
≠
1
)
A
(
n
=
1
)
FWT(A)=\begin{cases} (FWT(A_0+A_1),FWT(A_1))(n\ne1)\\ A(n=1) \end{cases}
FWT(A)={(FWT(A0+A1),FWT(A1))(n̸=1)A(n=1)
这么定义的原因(其实和or差不多):因为
A
0
A_0
A0的编号的最高位都是0,
A
1
A_1
A1的编号与
A
0
A_0
A0的编号的最高位变成1的结果一一对应,因为是and运算,所以
A
1
A_1
A1能到
A
0
A_0
A0里一一对应的贡献
然后是
I
F
W
T
IFWT
IFWT,推导:
已知
F
W
T
(
A
)
0
FWT(A)_0
FWT(A)0、
F
W
T
(
A
)
1
FWT(A)_1
FWT(A)1,求
A
0
A_0
A0、
A
1
A_1
A1
∵
F
W
T
(
A
)
0
=
F
W
T
(
A
0
)
+
F
W
T
(
A
1
)
∴
A
0
=
I
D
F
T
(
F
W
T
(
A
0
)
)
=
I
D
F
T
(
F
W
T
(
A
)
0
−
F
W
T
(
A
)
1
)
∵
F
W
T
(
A
)
1
=
F
W
T
(
A
1
)
∴
A
1
=
I
D
F
T
(
F
W
T
(
A
1
)
)
=
I
D
F
T
(
F
W
T
(
A
)
1
)
\because FWT(A)_0=FWT(A_0)+FWT(A_1)\\ \therefore A_0=IDFT(FWT(A_0))=IDFT(FWT(A)_0-FWT(A)_1)\\ \because FWT(A)_1=FWT(A_1)\\ \therefore A_1= IDFT(FWT(A_1))=IDFT(FWT(A)_1)
∵FWT(A)0=FWT(A0)+FWT(A1)∴A0=IDFT(FWT(A0))=IDFT(FWT(A)0−FWT(A)1)∵FWT(A)1=FWT(A1)∴A1=IDFT(FWT(A1))=IDFT(FWT(A)1)
总结:
I
F
W
T
(
A
)
=
{
(
I
F
W
T
(
A
0
−
A
1
)
,
I
F
W
T
(
A
1
)
)
(
n
≠
1
)
A
(
n
=
1
)
IFWT(A)=\begin{cases} (IFWT(A_0-A_1),IFWT(A_1))(n\ne1)\\ A(n=1) \end{cases}
IFWT(A)={(IFWT(A0−A1),IFWT(A1))(n̸=1)A(n=1)
然后上代码
inline void FWT(LL*A,const int fla)
{
for(rg int i=1;i<lenth;i<<=1)
for(rg int j=0;j<lenth;j+=(i<<1))
for(rg int k=0;k<i;k++)
A[j+k]+=A[j+k+i]*fla;
}
完
3.3xor运算(本质FWT)
3.3.1构造
哦不,这是最烦的xor运算,我的思路在xor下是最烦的
现在要求的是:
c
n
=
∑
i
⊕
j
=
n
a
i
b
j
c_n=\sum_{i\oplus j=n}a_ib_j
cn=i⊕j=n∑aibj
也要定义FWT(A),然而定义有一点烦:
update:这是新版本,比较清晰易懂:
符号说明:
p o p c o u n t ( x ) popcount(x) popcount(x)等于x在二进制下1的数量,我在下面简写为 p c ( x ) pc(x) pc(x)
F
W
T
(
A
)
=
(
∑
(
−
1
)
p
c
(
i
&
0
)
a
i
,
∑
(
−
1
)
p
c
(
i
&
1
)
a
i
⋅
⋅
⋅
∑
(
−
1
)
p
c
(
i
&
(
n
−
1
)
)
a
i
)
FWT(A)=(\sum (-1)^{pc(i\&0)}a_i,\sum (-1)^{pc(i\&1)}a_i···\sum (-1)^{pc(i\&(n-1))}a_i)
FWT(A)=(∑(−1)pc(i&0)ai,∑(−1)pc(i&1)ai⋅⋅⋅∑(−1)pc(i&(n−1))ai)
证明:
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)
F
W
T
(
A
)
∗
F
W
T
(
B
)
=
(
∑
(
−
1
)
p
c
(
i
&
0
)
a
i
,
∑
(
−
1
)
p
c
(
i
&
1
)
a
i
⋅
⋅
⋅
∑
(
−
1
)
p
c
(
i
&
(
n
−
1
)
)
a
i
)
∗
(
∑
(
−
1
)
p
c
(
i
&
0
)
b
i
,
∑
(
−
1
)
p
c
(
i
&
1
)
b
i
⋅
⋅
⋅
∑
(
−
1
)
p
c
(
i
&
(
n
−
1
)
)
b
i
)
=
(
(
∑
(
−
1
)
p
c
(
i
&
0
)
a
i
)
∗
(
(
∑
(
−
1
)
p
c
(
j
&
0
)
b
j
)
)
,
(
∑
(
−
1
)
p
c
(
i
&
1
)
a
i
)
∗
(
∑
(
−
1
)
p
c
(
j
&
1
)
b
j
)
⋅
⋅
⋅
(
∑
(
−
1
)
p
c
(
i
&
(
n
−
1
)
)
a
i
)
∗
(
∑
(
−
1
)
p
c
(
j
&
(
n
−
1
)
)
b
j
)
)
=
(
∑
(
−
1
)
p
c
(
i
⊕
j
&
0
)
a
i
∗
b
j
,
(
∑
(
−
1
)
p
c
(
i
⊕
j
&
1
)
a
i
∗
b
j
⋅
⋅
⋅
(
∑
(
−
1
)
p
c
(
i
⊕
j
&
(
n
−
1
)
)
a
i
∗
b
j
)
=
(
∑
(
−
1
)
p
c
(
k
&
0
)
∑
i
⊕
j
=
k
a
i
∗
b
j
,
∑
(
−
1
)
p
c
(
k
&
1
)
∑
i
⊕
j
=
k
a
i
∗
b
j
⋅
⋅
⋅
∑
(
−
1
)
p
c
(
k
&
(
n
−
1
)
)
∑
i
⊕
j
=
k
a
i
∗
b
j
)
=
F
W
T
(
A
⊕
B
)
\begin{aligned} FWT(A)*FWT(B)&=(\sum (-1)^{pc(i\&0)}a_i,\sum (-1)^{pc(i\&1)}a_i···\sum (-1)^{pc(i\&(n-1))}a_i)*(\sum (-1)^{pc(i\&0)}b_i,\sum (-1)^{pc(i\&1)}b_i···\sum (-1)^{pc(i\&(n-1))}b_i)\\ &=((\sum (-1)^{pc(i\&0)}a_i)*((\sum (-1)^{pc(j\&0)}b_j)),(\sum (-1)^{pc(i\&1)}a_i)*(\sum (-1)^{pc(j\&1)}b_j)···(\sum (-1)^{pc(i\&(n-1))}a_i)*(\sum (-1)^{pc(j\&(n-1))}b_j))\\ &=(\sum (-1)^{pc(i\oplus j\&0)}a_i*b_j,(\sum (-1)^{pc(i\oplus j\&1)}a_i*b_j···(\sum (-1)^{pc(i\oplus j\&(n-1))}a_i*b_j)\\ &=(\sum (-1)^{pc(k\&0)}\sum _{i\oplus j=k}a_i*b_j,\sum (-1)^{pc(k\&1)}\sum _{i\oplus j=k}a_i*b_j···\sum (-1)^{pc(k\&(n-1))}\sum _{i\oplus j=k}a_i*b_j)\\ &=FWT(A\oplus B) \end{aligned}
FWT(A)∗FWT(B)=(∑(−1)pc(i&0)ai,∑(−1)pc(i&1)ai⋅⋅⋅∑(−1)pc(i&(n−1))ai)∗(∑(−1)pc(i&0)bi,∑(−1)pc(i&1)bi⋅⋅⋅∑(−1)pc(i&(n−1))bi)=((∑(−1)pc(i&0)ai)∗((∑(−1)pc(j&0)bj)),(∑(−1)pc(i&1)ai)∗(∑(−1)pc(j&1)bj)⋅⋅⋅(∑(−1)pc(i&(n−1))ai)∗(∑(−1)pc(j&(n−1))bj))=(∑(−1)pc(i⊕j&0)ai∗bj,(∑(−1)pc(i⊕j&1)ai∗bj⋅⋅⋅(∑(−1)pc(i⊕j&(n−1))ai∗bj)=(∑(−1)pc(k&0)i⊕j=k∑ai∗bj,∑(−1)pc(k&1)i⊕j=k∑ai∗bj⋅⋅⋅∑(−1)pc(k&(n−1))i⊕j=k∑ai∗bj)=FWT(A⊕B)
下面是老版本,是一个不太标准的形式,你可以直接跳到3.3.2
符号说明:
p o p c o u n t ( x ) popcount(x) popcount(x)等于x在二进制下1的数量,我在下面简写为 p c ( x ) pc(x) pc(x)
逻辑运算符a?b:c 代表若a为真,那么值为b,若为假,值为c
F
W
T
(
A
)
=
(
∑
p
c
(
i
&
0
)
m
o
d
2
=
=
0
?
a
i
:
−
a
i
,
∑
p
c
(
i
&
1
)
m
o
d
2
=
=
0
?
a
i
:
−
a
i
,
∑
p
c
(
i
&
2
)
m
o
d
2
=
=
0
?
a
i
:
−
a
i
⋅
⋅
⋅
∑
p
c
(
i
&
(
n
−
1
)
)
m
o
d
2
=
=
0
?
a
i
:
−
a
i
)
FWT(A)=(\sum pc(i\&0)mod\ 2==0? a_i:-a_i,\sum pc(i\&1)mod\ 2==0? a_i:-a_i,\sum pc(i\&2)mod\ 2==0? a_i:-a_i···\sum pc(i\&(n-1))mod\ 2==0? a_i:-a_i)
FWT(A)=(∑pc(i&0)mod 2==0?ai:−ai,∑pc(i&1)mod 2==0?ai:−ai,∑pc(i&2)mod 2==0?ai:−ai⋅⋅⋅∑pc(i&(n−1))mod 2==0?ai:−ai)
不容易发现一件事:
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)
证明:
F
W
T
(
A
)
∗
F
W
T
(
B
)
=
(
∑
p
c
(
i
&
0
)
m
o
d
2
=
=
0
?
a
i
:
−
a
i
,
∑
p
c
(
i
&
1
)
m
o
d
2
=
=
0
?
a
i
:
−
a
i
,
∑
p
c
(
i
&
2
)
m
o
d
2
=
=
0
?
a
i
:
−
a
i
⋅
⋅
⋅
∑
p
c
(
i
&
(
n
−
1
)
)
m
o
d
2
=
=
0
?
a
i
:
−
a
i
)
∗
(
∑
p
c
(
i
&
0
)
m
o
d
2
=
=
0
?
b
i
:
−
b
i
,
∑
p
c
(
i
&
1
)
m
o
d
2
=
=
0
?
b
i
:
−
b
i
,
∑
p
c
(
i
&
2
)
m
o
d
2
=
=
0
?
b
i
:
−
b
i
⋅
⋅
⋅
∑
p
c
(
i
&
(
n
−
1
)
)
m
o
d
2
=
=
0
?
b
i
:
−
b
i
)
=
(
(
∑
p
c
(
i
&
0
)
m
o
d
2
=
=
0
?
a
i
:
−
a
i
)
∗
(
∑
p
c
(
j
&
0
)
m
o
d
2
=
=
0
?
b
j
:
−
b
j
)
,
(
∑
p
c
(
i
&
1
)
m
o
d
2
=
=
0
?
a
i
:
−
a
i
)
∗
(
∑
p
c
(
j
&
1
)
m
o
d
2
=
=
0
?
b
j
:
−
b
j
)
,
(
∑
p
c
(
i
&
2
)
m
o
d
2
=
=
0
?
a
i
:
−
a
i
)
∗
(
∑
p
c
(
j
&
2
)
m
o
d
2
=
=
0
?
b
j
:
−
b
j
)
⋅
⋅
⋅
(
∑
p
c
(
i
&
(
n
−
1
)
)
m
o
d
2
=
=
0
?
a
i
:
−
a
i
)
∗
(
∑
p
c
(
j
&
(
n
−
1
)
)
m
o
d
2
=
=
0
?
b
j
:
−
b
j
)
)
=
(
∑
p
c
(
(
i
⊕
j
)
&
0
)
m
o
d
2
=
=
0
?
a
i
∗
b
j
:
−
a
i
∗
b
j
,
∑
p
c
(
(
i
⊕
j
)
&
1
)
m
o
d
2
=
=
0
?
a
i
∗
b
j
:
−
a
i
∗
b
j
,
∑
p
c
(
(
i
⊕
j
)
&
2
)
m
o
d
2
=
=
0
?
a
i
∗
b
j
:
−
a
i
∗
b
j
⋅
⋅
⋅
∑
p
c
(
(
i
⊕
j
)
&
(
n
−
1
)
)
m
o
d
2
=
=
0
?
a
i
∗
b
j
:
−
a
i
∗
b
j
)
=
(
∑
p
c
(
k
&
0
)
m
o
d
2
=
=
0
?
∑
i
⊕
j
=
k
a
i
∗
b
j
:
−
∑
i
⊕
j
=
k
a
i
∗
b
j
,
∑
p
c
(
k
&
1
)
m
o
d
2
=
=
0
?
∑
i
⊕
j
=
k
a
i
∗
b
j
:
−
∑
i
⊕
j
=
k
a
i
∗
b
j
,
∑
p
c
(
k
&
2
)
m
o
d
2
=
=
0
?
∑
i
⊕
j
=
k
a
i
∗
b
j
:
−
∑
i
⊕
j
=
k
a
i
∗
b
j
⋅
⋅
⋅
∑
p
c
(
k
&
(
n
−
1
)
)
m
o
d
2
=
=
0
?
∑
i
⊕
j
=
k
a
i
∗
b
j
:
−
∑
i
⊕
j
=
k
a
i
∗
b
j
)
=
F
W
T
(
A
⊕
B
)
\begin{aligned} FWT(A)*FWT(B)&=(\sum pc(i\&0)mod\ 2==0? a_i:-a_i,\sum pc(i\&1)mod\ 2==0? a_i:-a_i,\sum pc(i\&2)mod\ 2==0? a_i:-a_i···\sum pc(i\&(n-1))mod\ 2==0? a_i:-a_i)*(\sum pc(i\&0)mod\ 2==0? b_i:-b_i,\sum pc(i\&1)mod\ 2==0? b_i:-b_i,\sum pc(i\&2)mod\ 2==0? b_i:-b_i···\sum pc(i\&(n-1))mod\ 2==0? b_i:-b_i)\\ &=((\sum pc(i\&0)mod\ 2==0? a_i:-a_i)*(\sum pc(j\&0)mod\ 2==0? b_j:-b_j),(\sum pc(i\&1)mod\ 2==0? a_i:-a_i)*(\sum pc(j\&1)mod\ 2==0? b_j:-b_j),(\sum pc(i\&2)mod\ 2==0? a_i:-a_i)*(\sum pc(j\&2)mod\ 2==0? b_j:-b_j)···(\sum pc(i\&(n-1))mod\ 2==0? a_i:-a_i)*(\sum pc(j\&(n-1))mod\ 2==0? b_j:-b_j))\\ &=(\sum pc((i\oplus j)\&0)mod\ 2==0? a_i*b_j:-a_i*b_j,\sum pc((i\oplus j)\&1)mod\ 2==0? a_i*b_j:-a_i*b_j,\sum pc((i\oplus j)\&2)mod\ 2==0? a_i*b_j:-a_i*b_j···\sum pc((i\oplus j)\&(n-1))mod\ 2==0? a_i*b_j:-a_i*b_j)\\ &=(\sum pc(k\&0)mod\ 2==0?\sum_{i \oplus j=k}a_i*b_j:-\sum_{i \oplus j=k}a_i*b_j,\sum pc(k\&1)mod\ 2==0? \sum_{i \oplus j=k}a_i*b_j:-\sum_{i \oplus j=k}a_i*b_j,\sum pc(k\&2)mod\ 2==0? \sum_{i \oplus j=k}a_i*b_j:-\sum_{i \oplus j=k}a_i*b_j···\sum pc(k\&(n-1))mod\ 2==0? \sum_{i \oplus j=k}a_i*b_j:-\sum_{i \oplus j=k}a_i*b_j)\\ &=FWT(A\oplus B) \end{aligned}
FWT(A)∗FWT(B)=(∑pc(i&0)mod 2==0?ai:−ai,∑pc(i&1)mod 2==0?ai:−ai,∑pc(i&2)mod 2==0?ai:−ai⋅⋅⋅∑pc(i&(n−1))mod 2==0?ai:−ai)∗(∑pc(i&0)mod 2==0?bi:−bi,∑pc(i&1)mod 2==0?bi:−bi,∑pc(i&2)mod 2==0?bi:−bi⋅⋅⋅∑pc(i&(n−1))mod 2==0?bi:−bi)=((∑pc(i&0)mod 2==0?ai:−ai)∗(∑pc(j&0)mod 2==0?bj:−bj),(∑pc(i&1)mod 2==0?ai:−ai)∗(∑pc(j&1)mod 2==0?bj:−bj),(∑pc(i&2)mod 2==0?ai:−ai)∗(∑pc(j&2)mod 2==0?bj:−bj)⋅⋅⋅(∑pc(i&(n−1))mod 2==0?ai:−ai)∗(∑pc(j&(n−1))mod 2==0?bj:−bj))=(∑pc((i⊕j)&0)mod 2==0?ai∗bj:−ai∗bj,∑pc((i⊕j)&1)mod 2==0?ai∗bj:−ai∗bj,∑pc((i⊕j)&2)mod 2==0?ai∗bj:−ai∗bj⋅⋅⋅∑pc((i⊕j)&(n−1))mod 2==0?ai∗bj:−ai∗bj)=(∑pc(k&0)mod 2==0?i⊕j=k∑ai∗bj:−i⊕j=k∑ai∗bj,∑pc(k&1)mod 2==0?i⊕j=k∑ai∗bj:−i⊕j=k∑ai∗bj,∑pc(k&2)mod 2==0?i⊕j=k∑ai∗bj:−i⊕j=k∑ai∗bj⋅⋅⋅∑pc(k&(n−1))mod 2==0?i⊕j=k∑ai∗bj:−i⊕j=k∑ai∗bj)=FWT(A⊕B)
这个证明写的我累死了
证完就好了
3.3.2计算
定义
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\ne1)\\ A(n=1) \end{cases}
FWT(A)={(FWT(A0+A1),FWT(A0−A1))(n̸=1)A(n=1)
我觉得FWT的脑洞真大,为啥这样就好了呢
就让我来解释一下吧
前提条件一样
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),通过这个把式子拆开
考虑当前二进制最高位,前
2
k
−
1
2^{k-1}
2k−1项的位置最高位都为0,所以and最高位之后一定不会是1所以
A
0
A_0
A0和
A
1
A_1
A1的贡献都是原符号,由于后
2
k
−
1
2^{k-1}
2k−1项的位置最高位都为1,所以
A
0
A_0
A0的贡献都是原符号,
A
1
A_1
A1的贡献符号反号
那么IFWT呢?
推导:
已知
F
W
T
(
A
)
0
FWT(A)_0
FWT(A)0、
F
W
T
(
A
)
1
FWT(A)_1
FWT(A)1,求
A
0
A_0
A0、
A
1
A_1
A1
∵
F
W
T
(
A
)
0
=
F
W
T
(
A
0
)
+
F
W
T
(
A
1
)
,
F
W
T
(
A
)
1
=
F
W
T
(
A
0
)
−
F
W
T
(
A
1
)
∴
A
0
=
I
D
F
T
(
F
W
T
(
A
0
)
)
=
I
D
F
T
(
F
W
T
(
A
)
0
+
F
W
T
(
A
)
1
2
)
,
A
1
=
I
D
F
T
(
F
W
T
(
A
1
)
)
=
I
D
F
T
(
F
W
T
(
A
)
0
−
F
W
T
(
A
)
1
2
)
\because FWT(A)_0=FWT(A_0)+FWT(A_1),FWT(A)_1=FWT(A_0)-FWT(A_1)\\ \therefore A_0=IDFT(FWT(A_0))=IDFT(\frac {FWT(A)_0+FWT(A)_1}2),A_1= IDFT(FWT(A_1))=IDFT(\frac {FWT(A)_0-FWT(A)_1}2)
∵FWT(A)0=FWT(A0)+FWT(A1),FWT(A)1=FWT(A0)−FWT(A1)∴A0=IDFT(FWT(A0))=IDFT(2FWT(A)0+FWT(A)1),A1=IDFT(FWT(A1))=IDFT(2FWT(A)0−FWT(A)1)
总结:
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
≠
1
)
A
(
n
=
1
)
IFWT(A)=\begin{cases} (\frac {IFWT(A_0)+IFWT(A_1)}{2},\frac {IFWT(A_0)-IFWT(A_1)}{2})(n\ne1)\\ A(n=1) \end{cases}
IFWT(A)={(2IFWT(A0)+IFWT(A1),2IFWT(A0)−IFWT(A1))(n̸=1)A(n=1)
代码
inline void FWT(LL*A,const int fla)
{
for(rg int i=1;i<lenth;i<<=1)
for(rg int j=0;j<lenth;j+=(i<<1))
for(rg int k=0;k<i;k++)
{
const int x=A[j+k],y=A[j+k+i];
A[j+k]=x+y;
A[j+k+i]=x-y;
if(fla==-1)A[j+k]/=2,A[j+k+i]/=2;
}
}
然后好像还有个优化,在一定条件下可以使用,就是把除法留到最后除,代码:
inline void FWT(LL*A,const int fla)
{
for(rg int i=1;i<lenth;i<<=1)
for(rg int j=0;j<lenth;j+=(i<<1))
for(rg int k=0;k<i;k++)
{
const int x=A[j+k],y=A[j+k+i];
A[j+k]=x+y;
A[j+k+i]=x-y;
}
if(fla==-1)
for(rg int i=0;i<lenth;i++)
A[i]/=lenth;
}
这就是xor的FWT啦
4总结
这个FWT写了好久,终于完结了,其实FWT本身代码并不长,关键在于理解。FWT用到的地方没FFT多,但依然值得学一下,拓宽思路
相关的题?
例题1(by update): NowCoder 295-H
题意,给出n个数(
n
≤
500000
,
a
i
≤
500000
n\leq500000,a_i\leq500000
n≤500000,ai≤500000),要求选出最少的数使异或值为所有数的异或值
解法,用0/1代表x值是否能取到,使用FWT异或卷积,容易发现最多做log次,每一次推复杂度
O
(
n
)
O(n)
O(n),做IDFT时由于只要求一个值,所以复杂度
O
(
n
)
O(n)
O(n),总复杂度
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
代码:
#include<cstdio>
#include<cctype>
#include<algorithm>
#define rg register
typedef long long LL;
template <typename T> inline T max(const T a,const T b){return a>b?a:b;}
template <typename T> inline T min(const T a,const T b){return a<b?a:b;}
template <typename T> inline void mind(T&a,const T b){a=a<b?a:b;}
template <typename T> inline void maxd(T&a,const T b){a=a>b?a:b;}
template <typename T> inline T abs(const T a){return a>0?a:-a;}
template <typename T> inline void swap(T&a,T&b){T c=a;a=b;b=c;}
template <typename T> inline T gcd(const T a,const T b){if(!b)return a;return gcd(b,a%b);}
template <typename T> inline T lcm(const T a,const T b){return a/gcd(a,b)*b;}
template <typename T> inline T square(const T x){return x*x;};
template <typename T> inline void read(T&x)
{
char cu=getchar();x=0;bool fla=0;
while(!isdigit(cu)){if(cu=='-')fla=1;cu=getchar();}
while(isdigit(cu))x=x*10+cu-'0',cu=getchar();
if(fla)x=-x;
}
template <typename T> inline void printe(const T x)
{
if(x>=10)printe(x/10);
putchar(x%10+'0');
}
template <typename T> inline void print(const T x)
{
if(x<0)putchar('-'),printe(-x);
else printe(x);
}
const int mod=998244353,lenth=524288;
int n,a[lenth],pc[lenth],val,f[lenth];
inline void FWT(int *A)
{
for(rg int i=1;i<lenth;i<<=1)
for(rg int j=0;j<lenth;j+=i<<1)
for(rg int k=0;k<i;k++)
{
const int x=A[j+k],y=A[j+k+i];
A[j+k]=(x+y)%mod;
A[j+k+i]=(x+mod-y)%mod;
}
}
int main()
{
read(n);
for(rg int i=1,x;i<=n;i++)read(x),a[i]=1,val^=x;
a[0]=1;
FWT(a);
for(rg int i=1;i<lenth;i++)pc[i]=pc[i^(i&-i)]+1;
for(rg int i=0;i<lenth;i++)f[i]=1;
for(rg int tim=0;tim<=19;tim++)
{
LL calc=0;
for(rg int i=0;i<lenth;i++)calc+=(pc[i&val]&1)?-f[i]:f[i];
calc%=mod;
if(calc)
{
print(n-tim);
return 0;
}
for(rg int i=0;i<lenth;i++)f[i]=(LL)f[i]*a[i]%mod;
}
return 0;
}
例题2(by update):
我的博客:CF 453 D
撒花结束!
由于写这篇博客写的匆忙,并且很多东西是自己推的,所以如果发现有误请及时提醒我哦