快速沃尔什变换支持多项式的位运算卷积
[C_i=sum_{joplus k = i}A_j imes B_k
]
(oplus)可以为(or,and,xor)
以(or)为例
(C_i=sumlimits_{j|k=i}A_jB_k)
令 (widehat{C}_i=sumlimits_{jsubseteq i}C_j)
(widehat{C}_i=sumlimits_{j|ksubseteq i}A_jB_k)
(widehat{C}_i=sumlimits_{jsubseteq i,ksubseteq i}A_jB_k)
(widehat{C}_i=widehat{A}_iwidehat{B}_i)
从 (A) 到 (widehat{A}) 的变换还有它的逆变换就是快速沃尔什变换进行的操作
可以发现或变换后所得的新的序列为是原序列的子集和
考虑将一个多项式(A)分为前半部分(A_0)和后半部分(A_1),其中(A_0)的下标最高位为(0),(A_1)的下标最高位为(1),( ext{merge})表示将两个多项式拼接,可得
[or:FWT(A) = ext{merge}(FWT(A_0),FWT(A_0)+FWT(A_1))
]
[UFWT(A) = ext{merge}(UFWT(A_0),UFWT(A_1)-UFWT(A_0))
]
[and:FWT(A) = ext{merge}(FWT(A_0)+FWT(A_1),FWT(A_1))
]
[UFWT(A) = ext{merge}(UFWT(A_0)-UFWT(A_1),UFWT(A_1))
]
[xor:FWT(A) = ext{merge}(FWT(A_0)+FWT(A_1),FWT(A_0)-FWT(A_1))
]
[UFWT(A) = ext{merge}(frac{UFWT(A_0)+UFWT(A_1)}{2},frac{UFWT(A_0)-UFWT(A_1)}{2})
]
(code:)
void FWT_or(ll *a,int type)
{
for(int len=1;len<n;len<<=1)
for(int i=0;i<n;i+=len<<1)
for(int j=i;j<i+len;++j)
a[j+len]=(a[j+len]+a[j]*type)%p;
}
void FWT_and(ll *a,int type)
{
for(int len=1;len<n;len<<=1)
for(int i=0;i<n;i+=len<<1)
for(int j=i;j<i+len;++j)
a[j]=(a[j]+a[j+len]*type)%p;
}
void FWT_xor(ll *a,int type)
{
for(int len=1;len<n;len<<=1)
{
for(int i=0;i<n;i+=len<<1)
{
for(int j=i;j<i+len;++j)
{
ll x=a[j],y=a[j+len];
a[j]=(x+y)%p,a[j+len]=(x-y)%p;
if(type<0) a[j]=a[j]*inv%p,a[j+len]=a[j+len]*inv%p;
}
}
}
}