FWT 学习笔记

FWT\texttt{FWT} 是一种类似于 FFT\texttt{FFT} 的一种变换,它可以实现在 O(nlogn)O(n\log n) 的时间内求出

Ck=i&j=kAiBjCk=ij=kAiBjCk=ij=kAiBj\begin{aligned} & C_k=\sum_{i\&j=k}A_iB_j\\ & C_k=\sum_{i\vert j=k}A_iB_j\\ & C_k=\sum_{i\oplus j=k}A_iB_j \end{aligned}

由于 FWT\texttt{FWT} 变换是一种线性变换,故满足 FWT(A)+FWT(B)=FWT(A+B)\texttt{FWT}(A)+\texttt{FWT}(B)=\texttt{FWT}(A+B)

类似于 FFT\texttt{FFT} 的方法,先将 AA 补成 2k2^k 的长度,每次将 AA 拆成两半,分别求 FWT\texttt{FWT} 即可。

因为 FWT\texttt{FWT}or,and,xor\texttt{or,and,xor} 三种形式,故也有三中不同的转移。

FWTor\color{red}\texttt{FWT}_{\texttt{or}}

FWT(A)={An=0(FWT(A0),FWT(A0)+FWT(A1))   n>0\texttt{FWT}(A)= \left\{ \begin{aligned} & A && n=0\\ & (\texttt{FWT}(A_0),\texttt{FWT}(A_0)+\texttt{FWT}(A_1)) ~~~&& n>0 \end{aligned} \right.

感性证明就是后面的一堆需要最高位为 00 的贡献,因为这是 or\texttt{or} 运算。

然后 UFWT\texttt{UFWT} 就是把那个 ++ 换成 -

考虑证明 FWT(AB)=FWT(A)×FWT(B)\texttt{FWT}(A\vert B)=\texttt{FWT}(A)\times \texttt{FWT}(B)。(这里的 ×\times 是按位乘)

FWT(AB)=FWT((AB)0,(AB)1)=FWT((AB)0,A0B1+A1B0+A1B1)=(FWT(A0B0),FWT(A0B0+A0B1+A1B0+A1B1))=(FWT(A0)×FWT(B0),FWT(A0)×FWT(B0)+FWT(A0)×FWT(B1)+FWT(A1)×FWT(B0)+FWT(A1)×FWT(B1))=(FWT(A0)×FWT(B0),(FWT(A0)+FWT(A1))×(FWT(B0)+FWT(B1)))=(FWT(A0),FWT(A0+A1))×(FWT(B0),FWT(B0+B1))=FWT(A)×FWT(B)\begin{aligned} \texttt{FWT}(A\vert B) &=\texttt{FWT}((A\vert B)_0,(A\vert B)_1)\\ & =\texttt{FWT}((A\vert B)_0,A_0\vert B_1+A_1\vert B_0+A_1\vert B_1)\\ & =(\texttt{FWT}(A_0\vert B_0),\texttt{FWT}(A_0\vert B_0+A_0\vert B_1+A_1\vert B_0+A_1\vert B_1))\\ & =(\texttt{FWT}(A_0)\times \texttt{FWT}(B_0),\\ \texttt{FWT}(A_0)\times \texttt{FWT}(B_0)+&\texttt{FWT}(A_0)\times \texttt{FWT}(B_1)+\texttt{FWT}(A_1)\times \texttt{FWT}(B_0)+\texttt{FWT}(A_1)\times \texttt{FWT}(B_1))\\ & =(\texttt{FWT}(A_0)\times \texttt{FWT}(B_0),(\texttt{FWT}(A_0)+\texttt{FWT}(A_1))\times (\texttt{FWT}(B_0)+\texttt{FWT}(B_1)))\\ & =(\texttt{FWT}(A_0),\texttt{FWT}(A_0+A_1))\times (\texttt{FWT}(B_0),\texttt{FWT}(B_0+B_1))\\ & =\texttt{FWT}(A)\times \texttt{FWT}(B) \end{aligned}

void FWT_or(int *a,int n,int ty)
{
    for(int i=2;i<=n;i<<=1)
    for(int j=0,p=i>>1;j<n;j+=i)
    for(int k=j;k<j+p;k++)
    a[k+p]+=ty*a[k];
    return;
}

FWTand\color{blue}\texttt{FWT}_{\texttt{and}}

FWT(A)={An=0(FWT(A0)+FWT(A1),FWT(A1))   n>0\texttt{FWT}(A)= \left\{ \begin{aligned} & A && n=0\\ & (\texttt{FWT}(A_0)+\texttt{FWT}(A_1),\texttt{FWT}(A_1)) ~~~&& n>0 \end{aligned} \right.

UFWT\texttt{UFWT} 也是将 ++ 变成 -,证明和上面的一样。

void FWT_and(int *a,int n,int ty)
{
    for(int i=2;i<=n;i<<=1)
    for(int j=0,p=i>>1;j<n;j+=i)
    for(int k=j;k<j+p;k++)
    a[k]+=ty*a[k+p];
    return;
}

FWTxor\color{deeppink}\texttt{FWT}_{\texttt{xor}}

FWT(A)={An=0(FWT(A0)+FWT(A1),(FWT(A0)FWT(A1))   n>0\texttt{FWT}(A)= \left\{ \begin{aligned} & A && n=0\\ & (\texttt{FWT}(A_0)+\texttt{FWT}(A_1),(\texttt{FWT}(A_0)-\texttt{FWT}(A_1)) ~~~&& n>0 \end{aligned} \right.

此时的 UFWT\texttt{UFWT} 变成 (UFWT(A0)+UFWT(A1)2,UFWT(A0)UFWT(A1)2)(\dfrac{\texttt{UFWT}(A_0)+\texttt{UFWT}(A_1)}{2},\dfrac{\texttt{UFWT}(A_0)-\texttt{UFWT}(A_1)}{2})懒得证了。

void FWT_xor(int *a,int n,int ty)
{
    for(int i=2;i<=n;i<<=1)
    for(int j=0,p=i>>1;j<n;j+=i)
    for(int k=j;k<j+p;k++)
    {
        int x=a[k],y=a[k+p];
        if(ty==1)a[k]=(x+y)%mod,a[k+p]=(x-y+mod)%mod;
        else a[k]=(x+y)%mod*inv2%mod,a[k+p]=(x-y+mod)%mod*inv2%mod;
    }
    return;
}