1前言

在之前学完了FFT稍微码了一些题、也学习了一下NTT相关的知识之后,我觉得有必要学习一下FWT,这篇博客就是阐述我对FWT的理解的

2介绍

2.1解决的问题

对于FFT,它的过程本质上是cn=∑i+j=nai∗bjc_n=\sum_{i+j=n}a_i*b_jcn​=i+j=n∑​ai​∗bj​
然后考虑一下那个i+j=ni+j=ni+j=n的情况,如果换个符号,比如i−j=ni-j=ni−j=n,那么想必你也会做,只要把B翻转就好了
在NTT的题中,其实i∗j=n(modp)i*j=n\pmod pi∗j=n(modp),在p有原根的时候也可以做,直接把i位置的数换到log⁡原根i\log_{原根}ilog原根​i,然后再做NTT,最后弄回来就好了(update:对怎么样的数有原根、对原根的性质有不理解的可以看我的博客原根哦)
那么对于i∣j=ni|j=ni∣j=n、i&j=ni\& j=ni&j=n、i⊕j=ni\oplus j=ni⊕j=n的情况怎么办?
可以用FWT来解决
这篇文章中用到的只是快速沃尔什变换(FWT)的一个特殊情况,有兴趣可以去网上搜一搜广义的快速沃尔什是干什么的

2.2文章中有可能用到的符号&特殊说明

首先,这篇博客中提到的n(多项式的项数)如无特殊说明都是2的幂次,方便处理,如果不为2的幂次,可以在高次加0系数
然后,对于一些公式,你可能会觉得比较长,其实只是因为我列的项数比较多导致的,你可以只看第一项来看懂我在推什么


对于一个一般的多项式f(x)=a0x0+a1x1+⋅⋅⋅+an−1xn−1f(x)=a_0x^0+a_1x^1+···+a_{n-1}x^{n-1}f(x)=a0​x0+a1​x1+⋅⋅⋅+an−1​xn−1
将其表示为(a0,a1,a2⋅⋅⋅an−1)(a_0,a_1,a_2···a_{n-1})(a0​,a1​,a2​⋅⋅⋅an−1​)


定义多项式加法
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)\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)=(a0,a1,a2⋅⋅⋅an−1)−(b0,b1,b2⋅⋅⋅bn−1)=(a0−b0,a1−b1,a2−b2⋅⋅⋅an−1−bn−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)=(a0,a1,a2⋅⋅⋅an−1)∗(b0,b1,b2⋅⋅⋅bn−1)=(a0∗b0,a1∗b1,a2∗b2⋅⋅⋅an−1∗bn−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)=(a0,a1,a2⋅⋅⋅an−1)@(b0,b1,b2⋅⋅⋅bn−1)=(∑i@j=0ai∗bj,∑i@j=1ai∗bj,∑i@j=2ai∗bj⋅⋅⋅∑i@j=n−1ai∗bj)\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(ai+bi)∗cj=∑i@j=x(ai∗cj+bi∗cj)=∑i@j=xai∗cj+∑i@j=xbi∗cj\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​​


另外对于一个多项式AAA,设n=2kn=2^kn=2k,定义A0A_0A0​为AAA的前2k−12^{k-1}2k−1个系数、定义A1A_1A1​为AAA的后2k−12^{k-1}2k−1个系数
定义运算A=(B,C)A=(B,C)A=(B,C)表示B这个多项式后面接上C等于A
用字母表示大概意思是:
(A,B)=((a0,a1,a2⋅⋅⋅ax−1),(b0,b1,b2⋅⋅⋅by−1))=(a0,a1,a2⋅⋅⋅ax−1,b0,b1,b2⋅⋅⋅by−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的大致思路

假设我们现在有两个多项式AAA、BBB以及一个位运算符@@@,思路和FFT相似,先求出某个多项式FWT(A)FWT(A)FWT(A)和FWT(B)FWT(B)FWT(B),然后对应相乘得到多项式FWT(C)FWT(C)FWT(C),最后进行IFWTIFWTIFWT,得出结果CCC

3实现

update:这里的前两个(and/or)更严格意义上来说是FMT,本篇博客提供FMT本身的相关内容,另一篇博客提供FMT的更多小应用

3.1or运算(本质FMT)

3.1.1构造

先来讲or运算吧
现在要求的是:cn=∑i∣j=naibjc_n=\sum_{i|j=n}a_ib_jcn​=i∣j=n∑​ai​bj​
定义FWT(A):
FWT(A)=(∑i∣0=0ai,∑i∣1=1ai,∑i∣2=2ai⋅⋅⋅∑i∣(n−1)=(n−1)ai)\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​)​
容易发现一件事:FWT(A∣B)=FWT(A)∗FWT(B)FWT(A|B)=FWT(A)*FWT(B)FWT(A∣B)=FWT(A)∗FWT(B)
证明:
FWT(A)∗FWT(B)=(∑i∣0=0ai,∑i∣1=1ai,∑i∣2=2ai⋅⋅⋅∑i∣(n−1)=(n−1)ai)∗(∑i∣0=0bi,∑i∣1=1bi,∑i∣2=2bi⋅⋅⋅∑i∣(n−1)=(n−1)bi)=((∑i∣0=0ai)∗(∑j∣0=0bj),(∑i∣1=1ai)∗(∑j∣1=1bj),(∑i∣2=2ai)∗(∑j∣2=2bj)⋅⋅⋅(∑i∣(n−1)=(n−1)ai)∗(∑j∣(n−1)=(n−1)bj))=(∑i∣j∣0=0ai∗bj,∑i∣j∣1=1ai∗bj,∑i∣j∣2=2ai∗bj⋅⋅⋅∑i∣j∣(n−1)=(n−1)ai∗bj)=(∑k∣0=0∑i∣j=kai∗bj,∑k∣1=1∑i∣j=kai∗bj,∑k∣2=2∑i∣j=kai∗bj⋅⋅⋅∑k∣(n−1)=(n−1)∑i∣j=kai∗bj)=FWT(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计算

我们可以递归定义
FWT(A)={(FWT(A0),FWT(A0+A1))(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)​
这么定义的原因:因为A0A_0A0​的编号的最高位都是0,A1A_1A1​的编号与A0A_0A0​的编号的最高位变成1的结果一一对应,因为是or运算,所以A0A_0A0​能到A1A_1A1​里一一对应的贡献
然后考虑IFWTIFWTIFWT(定义IFWT(FWT(A))=AIFWT(FWT(A))=AIFWT(FWT(A))=A),由于FWT(A+B)=FWT(A)+FWT(B)FWT(A+B)=FWT(A)+FWT(B)FWT(A+B)=FWT(A)+FWT(B)(这个证明不用说了吧,看我的定义,这个相当于乘法分配律拆一下就好了),可以列出IFWTIFWTIFWT的式子,推导:
已知FWT(A)0FWT(A)_0FWT(A)0​、FWT(A)1FWT(A)_1FWT(A)1​,求A0A_0A0​、A1A_1A1​
∵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)\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​)


总结:
IFWT(A)={(IFWT(A0),IFWT(A1−A0))(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差的不多
现在要求的是:cn=∑i&amp;j=naibjc_n=\sum_{i\&amp;j=n}a_ib_jcn​=i&j=n∑​ai​bj​
同样定义FWT(A):
FWT(A)=(∑i&amp;0=0ai,∑i&amp;1=1ai,∑i&amp;2=2ai⋅⋅⋅∑i&amp;(n−1)=(n−1)ai)\begin{aligned} FWT(A)=(\sum_{i\&amp;0=0}a_i,\sum_{i\&amp;1=1}a_i,\sum_{i\&amp;2=2}a_i···\sum_{i\&amp;(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​)​
同样的:FWT(A&amp;B)=FWT(A)∗FWT(B)FWT(A\&amp;B)=FWT(A)*FWT(B)FWT(A&B)=FWT(A)∗FWT(B)
证明:
FWT(A)∗FWT(B)=(∑i&amp;0=0ai,∑i&amp;1=1ai,∑i&amp;2=2ai⋅⋅⋅∑i&amp;(n−1)=(n−1)ai)∗(∑i&amp;0=0bi,∑i&amp;1=1bi,∑i&amp;2=2bi⋅⋅⋅∑i&amp;(n−1)=(n−1)bi)=((∑i&amp;0=0ai)∗(∑j&amp;0=0bj),(∑i&amp;1=1ai)∗(∑j&amp;1=1bj),(∑i&amp;2=2ai)∗(∑j&amp;2=2bj)⋅⋅⋅(∑i&amp;(n−1)=(n−1)ai)∗(∑j&amp;(n−1)=(n−1)bj))=(∑i&amp;j&amp;0=0ai∗bj,∑i&amp;j&amp;1=1ai∗bj,∑i&amp;j&amp;2=2ai∗bj⋅⋅⋅∑i&amp;j&amp;(n−1)=(n−1)ai∗bj)=(∑k&amp;0=0∑i&amp;j=kai∗bj,∑k&amp;1=1∑i&amp;j=kai∗bj,∑k&amp;2=2∑i&amp;j=kai∗bj⋅⋅⋅∑k&amp;(n−1)=(n−1)∑i&amp;j=kai∗bj)=FWT(A&amp;B)\begin{aligned} FWT(A)*FWT(B)&amp;=(\sum_{i\&amp;0=0}a_i,\sum_{i\&amp;1=1}a_i,\sum_{i\&amp;2=2}a_i···\sum_{i\&amp;(n-1)=(n-1)}a_i)*(\sum_{i\&amp;0=0}b_i,\sum_{i\&amp;1=1}b_i,\sum_{i\&amp;2=2}b_i···\sum_{i\&amp;(n-1)=(n-1)}b_i)\\ &amp;=((\sum_{i\&amp;0=0}a_i)*(\sum_{j\&amp;0=0}b_j),(\sum_{i\&amp;1=1}a_i)*(\sum_{j\&amp;1=1}b_j),(\sum_{i\&amp;2=2}a_i)*(\sum_{j\&amp;2=2}b_j)···(\sum_{i\&amp;(n-1)=(n-1)}a_i)*(\sum_{j\&amp;(n-1)=(n-1)}b_j))\\ &amp;=(\sum_{i\&amp;j\&amp;0=0}a_i*b_j,\sum_{i\&amp;j\&amp;1=1}a_i*b_j,\sum_{i\&amp;j\&amp;2=2}a_i*b_j···\sum_{i\&amp;j\&amp;(n-1)=(n-1)}a_i*b_j)\\ &amp;=(\sum_{k\&amp;0=0}\sum_{i\&amp;j=k}a_i*b_j,\sum_{k\&amp;1=1}\sum_{i\&amp;j=k}a_i*b_j,\sum_{k\&amp;2=2}\sum_{i\&amp;j=k}a_i*b_j···\sum_{k\&amp;(n-1)=(n-1)}\sum_{i\&amp;j=k}a_i*b_j)\\ &amp;=FWT(A\&amp;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计算

我们一样可以递归定义
FWT(A)={(FWT(A0+A1),FWT(A1))(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差不多):因为A0A_0A0​的编号的最高位都是0,A1A_1A1​的编号与A0A_0A0​的编号的最高位变成1的结果一一对应,因为是and运算,所以A1A_1A1​能到A0A_0A0​里一一对应的贡献
然后是IFWTIFWTIFWT,推导:
已知FWT(A)0FWT(A)_0FWT(A)0​、FWT(A)1FWT(A)_1FWT(A)1​,求A0A_0A0​、A1A_1A1​
∵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)\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​)


总结:
IFWT(A)={(IFWT(A0−A1),IFWT(A1))(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下是最烦的
现在要求的是:cn=∑i⊕j=naibjc_n=\sum_{i\oplus j=n}a_ib_jcn​=i⊕j=n∑​ai​bj​
也要定义FWT(A),然而定义有一点烦:
update:这是新版本,比较清晰易懂:

符号说明:
popcount(x)popcount(x)popcount(x)等于x在二进制下1的数量,我在下面简写为pc(x)pc(x)pc(x)

FWT(A)=(∑(−1)pc(i&amp;0)ai,∑(−1)pc(i&amp;1)ai⋅⋅⋅∑(−1)pc(i&amp;(n−1))ai)FWT(A)=(\sum (-1)^{pc(i\&amp;0)}a_i,\sum (-1)^{pc(i\&amp;1)}a_i···\sum (-1)^{pc(i\&amp;(n-1))}a_i) FWT(A)=(∑(−1)pc(i&0)ai​,∑(−1)pc(i&1)ai​⋅⋅⋅∑(−1)pc(i&(n−1))ai​)
证明:FWT(A⊕B)=FWT(A)∗FWT(B)FWT(A\oplus B)=FWT(A)*FWT(B)FWT(A⊕B)=FWT(A)∗FWT(B)
FWT(A)∗FWT(B)=(∑(−1)pc(i&amp;0)ai,∑(−1)pc(i&amp;1)ai⋅⋅⋅∑(−1)pc(i&amp;(n−1))ai)∗(∑(−1)pc(i&amp;0)bi,∑(−1)pc(i&amp;1)bi⋅⋅⋅∑(−1)pc(i&amp;(n−1))bi)=((∑(−1)pc(i&amp;0)ai)∗((∑(−1)pc(j&amp;0)bj)),(∑(−1)pc(i&amp;1)ai)∗(∑(−1)pc(j&amp;1)bj)⋅⋅⋅(∑(−1)pc(i&amp;(n−1))ai)∗(∑(−1)pc(j&amp;(n−1))bj))=(∑(−1)pc(i⊕j&amp;0)ai∗bj,(∑(−1)pc(i⊕j&amp;1)ai∗bj⋅⋅⋅(∑(−1)pc(i⊕j&amp;(n−1))ai∗bj)=(∑(−1)pc(k&amp;0)∑i⊕j=kai∗bj,∑(−1)pc(k&amp;1)∑i⊕j=kai∗bj⋅⋅⋅∑(−1)pc(k&amp;(n−1))∑i⊕j=kai∗bj)=FWT(A⊕B)\begin{aligned} FWT(A)*FWT(B)&amp;=(\sum (-1)^{pc(i\&amp;0)}a_i,\sum (-1)^{pc(i\&amp;1)}a_i···\sum (-1)^{pc(i\&amp;(n-1))}a_i)*(\sum (-1)^{pc(i\&amp;0)}b_i,\sum (-1)^{pc(i\&amp;1)}b_i···\sum (-1)^{pc(i\&amp;(n-1))}b_i)\\ &amp;=((\sum (-1)^{pc(i\&amp;0)}a_i)*((\sum (-1)^{pc(j\&amp;0)}b_j)),(\sum (-1)^{pc(i\&amp;1)}a_i)*(\sum (-1)^{pc(j\&amp;1)}b_j)···(\sum (-1)^{pc(i\&amp;(n-1))}a_i)*(\sum (-1)^{pc(j\&amp;(n-1))}b_j))\\ &amp;=(\sum (-1)^{pc(i\oplus j\&amp;0)}a_i*b_j,(\sum (-1)^{pc(i\oplus j\&amp;1)}a_i*b_j···(\sum (-1)^{pc(i\oplus j\&amp;(n-1))}a_i*b_j)\\ &amp;=(\sum (-1)^{pc(k\&amp;0)}\sum _{i\oplus j=k}a_i*b_j,\sum (-1)^{pc(k\&amp;1)}\sum _{i\oplus j=k}a_i*b_j···\sum (-1)^{pc(k\&amp;(n-1))}\sum _{i\oplus j=k}a_i*b_j)\\ &amp;=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

符号说明:
popcount(x)popcount(x)popcount(x)等于x在二进制下1的数量,我在下面简写为pc(x)pc(x)pc(x)
逻辑运算符a?b:c 代表若a为真,那么值为b,若为假,值为c

FWT(A)=(∑pc(i&amp;0)mod2==0?ai:−ai,∑pc(i&amp;1)mod2==0?ai:−ai,∑pc(i&amp;2)mod2==0?ai:−ai⋅⋅⋅∑pc(i&amp;(n−1))mod2==0?ai:−ai)FWT(A)=(\sum pc(i\&amp;0)mod\ 2==0? a_i:-a_i,\sum pc(i\&amp;1)mod\ 2==0? a_i:-a_i,\sum pc(i\&amp;2)mod\ 2==0? a_i:-a_i···\sum pc(i\&amp;(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​)
不容易发现一件事:FWT(A⊕B)=FWT(A)∗FWT(B)FWT(A\oplus B)=FWT(A)*FWT(B)FWT(A⊕B)=FWT(A)∗FWT(B)
证明:
FWT(A)∗FWT(B)=(∑pc(i&amp;0)mod2==0?ai:−ai,∑pc(i&amp;1)mod2==0?ai:−ai,∑pc(i&amp;2)mod2==0?ai:−ai⋅⋅⋅∑pc(i&amp;(n−1))mod2==0?ai:−ai)∗(∑pc(i&amp;0)mod2==0?bi:−bi,∑pc(i&amp;1)mod2==0?bi:−bi,∑pc(i&amp;2)mod2==0?bi:−bi⋅⋅⋅∑pc(i&amp;(n−1))mod2==0?bi:−bi)=((∑pc(i&amp;0)mod2==0?ai:−ai)∗(∑pc(j&amp;0)mod2==0?bj:−bj),(∑pc(i&amp;1)mod2==0?ai:−ai)∗(∑pc(j&amp;1)mod2==0?bj:−bj),(∑pc(i&amp;2)mod2==0?ai:−ai)∗(∑pc(j&amp;2)mod2==0?bj:−bj)⋅⋅⋅(∑pc(i&amp;(n−1))mod2==0?ai:−ai)∗(∑pc(j&amp;(n−1))mod2==0?bj:−bj))=(∑pc((i⊕j)&amp;0)mod2==0?ai∗bj:−ai∗bj,∑pc((i⊕j)&amp;1)mod2==0?ai∗bj:−ai∗bj,∑pc((i⊕j)&amp;2)mod2==0?ai∗bj:−ai∗bj⋅⋅⋅∑pc((i⊕j)&amp;(n−1))mod2==0?ai∗bj:−ai∗bj)=(∑pc(k&amp;0)mod2==0?∑i⊕j=kai∗bj:−∑i⊕j=kai∗bj,∑pc(k&amp;1)mod2==0?∑i⊕j=kai∗bj:−∑i⊕j=kai∗bj,∑pc(k&amp;2)mod2==0?∑i⊕j=kai∗bj:−∑i⊕j=kai∗bj⋅⋅⋅∑pc(k&amp;(n−1))mod2==0?∑i⊕j=kai∗bj:−∑i⊕j=kai∗bj)=FWT(A⊕B)\begin{aligned} FWT(A)*FWT(B)&amp;=(\sum pc(i\&amp;0)mod\ 2==0? a_i:-a_i,\sum pc(i\&amp;1)mod\ 2==0? a_i:-a_i,\sum pc(i\&amp;2)mod\ 2==0? a_i:-a_i···\sum pc(i\&amp;(n-1))mod\ 2==0? a_i:-a_i)*(\sum pc(i\&amp;0)mod\ 2==0? b_i:-b_i,\sum pc(i\&amp;1)mod\ 2==0? b_i:-b_i,\sum pc(i\&amp;2)mod\ 2==0? b_i:-b_i···\sum pc(i\&amp;(n-1))mod\ 2==0? b_i:-b_i)\\ &amp;=((\sum pc(i\&amp;0)mod\ 2==0? a_i:-a_i)*(\sum pc(j\&amp;0)mod\ 2==0? b_j:-b_j),(\sum pc(i\&amp;1)mod\ 2==0? a_i:-a_i)*(\sum pc(j\&amp;1)mod\ 2==0? b_j:-b_j),(\sum pc(i\&amp;2)mod\ 2==0? a_i:-a_i)*(\sum pc(j\&amp;2)mod\ 2==0? b_j:-b_j)···(\sum pc(i\&amp;(n-1))mod\ 2==0? a_i:-a_i)*(\sum pc(j\&amp;(n-1))mod\ 2==0? b_j:-b_j))\\ &amp;=(\sum pc((i\oplus j)\&amp;0)mod\ 2==0? a_i*b_j:-a_i*b_j,\sum pc((i\oplus j)\&amp;1)mod\ 2==0? a_i*b_j:-a_i*b_j,\sum pc((i\oplus j)\&amp;2)mod\ 2==0? a_i*b_j:-a_i*b_j···\sum pc((i\oplus j)\&amp;(n-1))mod\ 2==0? a_i*b_j:-a_i*b_j)\\ &amp;=(\sum pc(k\&amp;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\&amp;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\&amp;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\&amp;(n-1))mod\ 2==0? \sum_{i \oplus j=k}a_i*b_j:-\sum_{i \oplus j=k}a_i*b_j)\\ &amp;=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计算

定义
FWT(A)={(FWT(A0+A1),FWT(A0−A1))(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的脑洞真大,为啥这样就好了呢
就让我来解释一下吧
前提条件一样FWT(A+B)=FWT(A)+FWT(B)FWT(A+B)=FWT(A)+FWT(B)FWT(A+B)=FWT(A)+FWT(B),通过这个把式子拆开
考虑当前二进制最高位,前2k−12^{k-1}2k−1项的位置最高位都为0,所以and最高位之后一定不会是1所以A0A_0A0​和A1A_1A1​的贡献都是原符号,由于后2k−12^{k-1}2k−1项的位置最高位都为1,所以A0A_0A0​的贡献都是原符号,A1A_1A1​的贡献符号反号
那么IFWT呢?
推导:
已知FWT(A)0FWT(A)_0FWT(A)0​、FWT(A)1FWT(A)_1FWT(A)1​,求A0A_0A0​、A1A_1A1​
∵FWT(A)0=FWT(A0)+FWT(A1),FWT(A)1=FWT(A0)−FWT(A1)∴A0=IDFT(FWT(A0))=IDFT(FWT(A)0+FWT(A)12),A1=IDFT(FWT(A1))=IDFT(FWT(A)0−FWT(A)12)\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​​)


总结:
IFWT(A)={(IFWT(A0)+IFWT(A1)2,IFWT(A0)−IFWT(A1)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,ai≤500000n\leq500000,a_i\leq500000n≤500000,ai​≤500000),要求选出最少的数使异或值为所有数的异或值
解法,用0/1代表x值是否能取到,使用FWT异或卷积,容易发现最多做log次,每一次推复杂度O(n)O(n)O(n),做IDFT时由于只要求一个值,所以复杂度O(n)O(n)O(n),总复杂度O(nlogn)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
撒花结束!
由于写这篇博客写的匆忙,并且很多东西是自己推的,所以如果发现有误请及时提醒我哦

快速沃尔什变换(FWT)相关推荐

  1. 解题报告(一)快速沃尔什变换FWT(ACM / OI)超高质量题解

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...

  2. [学习笔记]快速沃尔什变换 (FWT)

    FWT的简介 一般 FWT \text{FWT} FWT用来解决一下问题: C k = ∑ i ∣ j = k A i B j C_k=\sum_{i|j=k}A_iB_j Ck​=∑i∣j=k​Ai ...

  3. 快速沃尔什变换(FWT)及K进制异或卷积快速子集变换(FST)讲解

    前言: $FWT$是用来处理位运算(异或.与.或)卷积的一种变换.位运算卷积是什么?形如$f[i]=\sum\limits_{j\oplus k==i}^{ }g[j]*h[k]$的卷积形式(其中$\ ...

  4. 【learning】快速沃尔什变换FWT

    问题描述 已知\(A(x)\)和\(B(x)\),\(C[i]=\sum\limits_{j\otimes k=i}A[j]*B[k]\),求\(C\) 其中\(\otimes\)是三种位运算的其中一 ...

  5. 快速沃尔什变换(FWT) 学习笔记

    最近在做多校联赛的题目,发现有一道题需要用到FWT,于是我就去学了一下.膜拜一下大神,本篇博客仅对这篇博客进行一些细节上的补充. FWT要解决的问题是 Ck=∑i⊕j=kai∗bi {C}_{k}=\ ...

  6. 《小学生都能看懂的快速沃尔什变换从入门到升天教程》(FWT / FMT / FMI)(最最严谨清晰的证明!零基础也能得学会!)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 0x00 卷积 0x01 多项式 0x02 卷积的定义 0x03 卷积的基本性质 0x04 位运 ...

  7. 快速沃尔什变换(FWT)讲解 解决集合卷积的方法

    由于某次CSDN更新,文章样式已经丢失,大量公式无法正常显示,本博客也不再维护. 请到快速沃尔什变换FWT查看,有更加完整的公式讲解. 能看到这篇博客的人,一定知道FWT是干什么的.(什么?你不知道? ...

  8. [多项式算法](Part 4)FWT 快速沃尔什变换 学习笔记

    其他多项式算法传送门: [多项式算法](Part 1)FFT 快速傅里叶变换 学习笔记 [多项式算法](Part 2)NTT 快速数论变换 学习笔记 [多项式算法](Part 3)MTT 任意模数FF ...

  9. [模板] 快速沃尔什变换

    快速沃尔什变换 快速沃尔什变换是求这样的式子: 对序列 \(A\), \(B\), 求序列 \(C\), 使得 \[ C_{i}=\sum_{j \oplus k} A_{j} B_{k} \] 其中 ...

最新文章

  1. asp.net 页面之间跳转的几种方法及区别(转)
  2. 像素位移_1亿像素放大也清晰 OPPO Ace2超清四摄解析
  3. C# 接口持有结构体会导致装箱问题
  4. QT中使用OpenGL绘制图形
  5. c/c++ 字符串分割
  6. matlab矩阵 0,matlab zeros初始化为0矩阵
  7. prototype.js1.5平面结果导读图
  8. php中如何存储多个文本框,php-如何将每个字符的文本框拆分为多个子文本框
  9. JavaScript——面向对象之继承(原型对象)与多态(重载、重写)
  10. 江苏省计算机c语言考试题库,2020上半年江苏省计算机等级考试辅导教程:二级C语言上机考试题库...
  11. Python基础包含哪些内容?学习什么?
  12. C. Edgy Trees(并查集+细节)
  13. 暴雪战网下载各个版本与修改默认登陆地点方法
  14. 用友通10.1禁止安装在SQL2005
  15. 感慨鸿蒙谁为情种,开辟鸿蒙,谁为情种……
  16. Jenkins高级篇之Pipeline语法篇-2-第一个Pipeline脚本练习
  17. 深入理解CSS:font metrics, line-height 以及 vertical-align
  18. android 手机同时使用wifi 和数据流量(3G/4G...)
  19. 毛细管电泳分离条件的小波神经网络优化
  20. 狂神JavaWeb课程笔记

热门文章

  1. 字符串转换成ascii码
  2. kafka高可用集群课程介绍
  3. SpringBoot_数据访问-整合MyBatis(一)-基础环境搭建
  4. plsql(轻量版)_异常处理机制
  5. std和android空间,ANDROID平台通讯中STDM加密技术的应用
  6. Xshell、Xftp入门使用
  7. 《Linux From Scratch》第三部分:构建LFS系统 第六章:安装基本的系统软件- 6.12. File-5.22...
  8. 敏捷方法在测试计划中的应用
  9. 极客班C++ STL(容器)第二周笔记
  10. 软工实践练习一——使用Git进行代码管理心得