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

FWT要解决的问题是

Ck=ij=kaibi

tf(A)$tf\left(A \right)$是对A做一次FWT的结果，结果也是一个2^k的向量，如果可以做FWT，需要满足的条件是：

tf(C)=tf(A)tf(B)

tf(A+B)$tf\left(A+B \right)$
=(tf(A0+B0)+tf(A1+B1),tf(A0+B0)tf(A1+B1))$=\left(tf\left({A}_{0}+{B}_{0} \right)+tf\left({A}_{1} +{B}_{1} \right),tf\left({A}_{0}+{B}_{0} \right)-tf\left({A}_{1} +{B}_{1} \right)\right)$

=(tf(A0)+tf(B0)+tf(A1)+tf(B1),tf(A0)+tf(B0)tf(A1)tf(B1))$=\left(tf\left({A}_{0}\right)+tf\left({B}_{0} \right)+tf\left({A}_{1}\right) +tf\left({B}_{1} \right),tf\left({A}_{0}\right)+tf\left({B}_{0} \right)-tf\left({A}_{1} \right)-tf\left({B}_{1} \right)\right)$
=(tf(A0)+tf(A1),tf(A0)tf(A1))+(tf(B0)+tf(B1),tf(B0)tf(B1))$=(tf\left({A}_{0}\right)+tf\left({A}_{1}\right),tf\left({A}_{0}\right)-tf\left({A}_{1} \right))+(tf\left({B}_{0}\right)+tf\left({B}_{1}\right),tf\left({B}_{0}\right)-tf\left({B}_{1} \right))$
=tf(A)+tf(B)$=tf(A)+tf(B)$

tf(A)=(tf(A0)+tf(A1),tf(A0)tf(A1))$tf(A)=(tf({A}_{0})+tf({A}_{1}),tf({A}_{0})-tf({A}_{1}))$
tf(B)=(tf(B0)+tf(B1),tf(B0)tf(B1))$tf(B)=(tf({B}_{0})+tf({B}_{1}),tf({B}_{0})-tf({B}_{1}))$
tf(A)tf(B)$tf(A)*tf(B)$
=((tf(A0)+tf(A1))(tf(B0)+tf(B1)),(tf(A0)tf(A1))(tf(B0)tf(B1))$=((tf({A}_{0})+tf({A}_{1}))*(tf({B}_{0})+tf({B}_{1})),(tf({A}_{0})-tf({A}_{1}))*(tf({B}_{0})-tf({B}_{1}))$

=(tf(A0)tf(B0)+tf(A0)tf(B1)+tf(A1)tf(B0)+tf(A1)tf(B1),tf(A0)tf(B0)tf(A0)tf(B1)tf(A1)tf(B0)+tf(A1)tf(B1))$=(tf({A}_{0})*tf({B}_{0})+tf({A}_{0})*tf({B}_{1})+tf({A}_{1})*tf({B}_{0})+tf({A}_{1})*tf({B}_{1}),tf({A}_{0})*tf({B}_{0})-tf({A}_{0})*tf({B}_{1})-tf({A}_{1})*tf({B}_{0})+tf({A}_{1})*tf({B}_{1}))$

=(tf(A0@B0)+tf(A1@B1)+tf(A0@B1)+tf(A1@B0)tf(A0@B0)+tf(A1@B1)tf(A0@B1)tf(A1@B0))$=(tf({A}_{0}@{B}_{0})+tf({A}_{1}@{B}_{1})+tf({A}_{0}@{B}_{1})+tf({A}_{1}@{B}_{0})，tf({A}_{0}@{B}_{0})+tf({A}_{1}@{B}_{1})−tf({A}_{0}@{B}_{1})−tf({A}_{1}@{B}_{0}))$

tf(C)=tf(C0,C1)$tf(C)=tf({C}_{0},{C}_{1})$
=tf(A0@B0+A1@B1,A0@B1+A1@B0)$=tf({A}_{0}@{B}_{0}+{A}_{1}@{B}_{1},{A}_{0}@{B}_{1}+{A}_{1}@{B}_{0})$
=(tf(A0@B0+A1@B1)+tf(A0@B1+A1@B0),tf(A0@B0+A1@B1)tf(A0@B1+A1B0))$=(tf({A}_{0}@{B}_{0}+{A}_{1}@{B}_{1})+tf({A}_{0}@{B}_{1}+{A}_{1}@{B}_{0}),tf({A}_{0}@{B}_{0}+{A}_{1}@{B}_{1})-tf({A}_{0}@{B}_{1}+{A}_{1}*{B}_{0}))$
=(tf(A0@B0)+tfA1@B1)+tf(A0@B1)+tf(A1@B0),tf(A0@B0)+tf(A1@B1)tf(A0@B1)tf(A1@B0))$=(tf({A}_{0}@{B}_{0})+tf{A}_{1}@{B}_{1})+tf({A}_{0}@{B}_{1})+tf({A}_{1}@{B}_{0}),tf({A}_{0}@{B}_{0})+tf({A}_{1}@{B}_{1})-tf({A}_{0}@{B}_{1})-tf({A}_{1}@{B}_{0}))$
=(tf(A0)tf(B0)+tf(A0)tf(B1)+tf(A1)tf(B0)+tf(A1)tf(B1),tf(A0)tf(B0)tf(A0)tf(B1)tf(A1)tf(B0)+tf(A1)tf(B1))$=(tf({A}_{0})*tf({B}_{0})+tf({A}_{0})*tf({B}_{1})+tf({A}_{1})*tf({B}_{0})+tf({A}_{1})*tf({B}_{1}),tf({A}_{0})*tf({B}_{0})-tf({A}_{0})*tf({B}_{1})-tf({A}_{1})*tf({B}_{0})+tf({A}_{1})*tf({B}_{1}))$
=((tf(A0)+tf(A1))(tf(B0)+tf(B1)),(tf(A0)tf(A1))(tf(B0)tf(B1))$=((tf({A}_{0})+tf({A}_{1}))*(tf({B}_{0})+tf({B}_{1})),(tf({A}_{0})-tf({A}_{1}))*(tf({B}_{0})-tf({B}_{1}))$
=tf(C)$=tf(C)$
tf$tf$函数的你函数ntf$ntf$也是类似。

xor
tf(A)=(tf(A0)+tf(A1),tf(A0)tf(A1))$tf(A)=(tf({A}_{0})+tf({A}_{1}),tf({A}_{0})-tf({A}_{1}))$
utf(A)=(utf(A0+A12),(A0A12)$utf(A)=(utf(\frac{{A}_{0}+{A}_{1}}{2}),(\frac{{A}_{0}-{A}_{1}}{2})$
and
tf(A)=(tf(A0)+tf(A1),tf(A1))$tf(A)=(tf({A}_{0})+tf({A}_{1}),tf({A}_{1}))$
utf(A)=(utf(A0)utf(A1),utf(A1))$utf(A)=(utf({A}_{0})-utf({A}_{1}),utf({A}_{1}))$
or
tf(A)=(tf(A0),tf(A1)+tf(A0))$tf(A)=(tf({A}_{0}),tf({A}_{1})+tf({A}_{0}))$
utf(A)=(utf(A0),utf(A1)utf(A0))$utf(A)=(utf({A}_{0}),utf({A}_{1})-utf({A}_{0}))$

void FWT(int a[],int n)
{
for(int d=1;d<n;d<<=1)
for(int m=d<<1,i=0;i<n;i+=m)
for(int j=0;j<d;j++)
{
int x=a[i+j],y=a[i+j+d];
a[i+j]=(x+y)%mod,a[i+j+d]=(x-y+mod)%mod;
//xor:a[i+j]=x+y,a[i+j+d]=(x-y+mod)%mod;
//and:a[i+j]=x+y;
//or:a[i+j+d]=x+y;
}
}

void UFWT(int a[],int n)
{
for(int d=1;d<n;d<<=1)
for(int m=d<<1,i=0;i<n;i+=m)
for(int j=0;j<d;j++)
{
int x=a[i+j],y=a[i+j+d];
a[i+j]=1LL*(x+y)*rev%mod,a[i+j+d]=(1LL*(x-y)*rev%mod+mod)%mod;
//rev表示2在模mod下的逆元
//xor:a[i+j]=(x+y)/2,a[i+j+d]=(x-y)/2;
//and:a[i+j]=x-y;
//or:a[i+j+d]=y-x;
}
}
void solve(int a[],int b[],int n)
{
FWT(a,n);
FWT(b,n);
for(int i=0;i<n;i++) a[i]=1LL*a[i]*b[i]%mod;
UFWT(a,n);
}