能轻松背板子的FWT(快速沃尔什变换) FWT应用 结论 原理 FWT板子 FWT搞完
我不知道(FWT)的严格定义
百度百科和维基都不知道给一坨什么**东西
FWT(Fast Walsh Fransform),中文名快速沃尔什变换
然后我也不知道(FWT)到底是什么你们怎么念FWT的反正我念扶卧塔
(FFT)当然可以做多项式卷积
形如(C(k)=sum_{i+j=k}f[i]g[j]),很简单,大家都会
由于有这个性质所以也可做分治(FFT)
但是如果把(i+j)换一下操作符
变成(C(k)=sum_{i???j=k}f[i]g[j])
其中(???)可以是(or,and,xor)三种运算
这时就要用(FWT)来做特殊卷积了
结论
类似(FFT),把当前多项式(A)拆成前一半(A_0)和后一半(A_1)
注意不是奇数项和偶数项,只是前一半和后一半……(狗头保命)
也可知(FWT)也只能处理长度为(2)的次幂的多项式
or
and
xor
(+)就是每一位值加起来,不知道(merge)是什么东西?
其实就是两个多项式前后拼起来……(狗头保命)
所以就算不清楚原理背下结论也很容易写出板子
由于某些原因原理完全可以跳过不看
但还是懂一下比较好
原理
清真のor&and
令(FWT(A)=A',A'[i]=sum_{i|j=i}A[j]),(B)同理
(i|j=i)就表示二进制下(j)一定是(i)的子集
这样好像可以满足(C'[i]=A'[i]*B'[i]),不懂可以写一写
大概就是(A'[i])已经包含下标或起来(=i)的(A),(B'[i])也是
所以(A'[i],B'[i])里包含的每个数下标或起来都等于(i)
自然两个和乘起来就是两两配对的总和,即(C'[i]=A'[i]*B'[i])
肯定不能枚举(i)的二进制子集因为太沙雕
然后试着把(A)拆成前半段(A_0)和后半段(A_1)
如果知道(FWT(A_0),FWT(A_1)),可以知道(FWT(A))吗是个学过FFT的人都知道应该可以
设当前多项式(A)的长度为(2^k),(A_0,A_1)长度为(2^{k-1})
(FWT(A))的前半段表示(A)的二进制位第(k)位填(0)
那么是它子集的好像有(FWT(A_0))
(FWT(A))的前半段表示(A)的二进制位第(k)位填(1)
是它子集的不仅有(FWT(A_1)),还有(FWT(A_0))大概就是这个亚子其实我也不是很清楚
所以(FWT(A))前半段就是(FWT(A_0)),后半段就是(FWT(A_0),FWT(A_1))加起来
于是就有了结论的(FWT(A)=merge(FWT(A_0),FWT(A_0)+FWT(A_1)))
至于(IFWT),就是已知(A_0',A_1'),求(A_0,A_1)
由于(A_0'=A_0,A_1'=A_0+A_1),所以(A_0=A_0',A_1=A_1'-A_0')
这样就有了两个简单易懂易背的结论
对于(and)也可同理推一波操作,和(or)很像,结论、代码也很像
打对(or)就可以打对(and).jpg
鬼畜のxor
一看(or)和(and)的结论就很清真,其实是因为(or)和(and)很像
(xor)奇怪就奇怪在运算和(or,and)有很大区别
但(xor)卷积还是有优化的方法
令(i&j)中(1)数量的奇偶性为(i)与(j)的奇偶性,那么(i)与(k)的奇偶性异或(j)和(k)的奇偶性等于(i⊕j)和(k)的奇偶性
设(f(x))表示(x)在二进制下(1)的个数
如果这样的话
对于(or),由于(or,and)同理,令
结果和上面的是一样的于是由这两种运算的优美性质自然而然的可以得到xor的规律
于是你就知道为什么xor那么鬼畜
FWT板子
#define mod 998244353
#define inv2 499122177
inline void fwt_or(ll f[],ll len,ll inv)
{
for (ll i=1;i<len;i<<=1)
for (ll j=0;j<len;j+=(i<<1))
for (ll k=0;k<i;++k)
f[i+j+k]=(inv*f[j+k]+f[i+j+k]+mod)%mod;
}
inline void fwt_and(ll f[],ll len,ll inv)
{
for (ll i=1;i<len;i<<=1)
for (ll j=0;j<len;j+=(i<<1))
for (ll k=0;k<i;++k)
f[j+k]=(f[j+k]+inv*f[i+j+k]+mod)%mod;
}
inline void fwt_xor(ll f[],ll len,ll inv)
{
for (ll i=1;i<len;i<<=1)
for (ll j=0;j<len;j+=(i<<1))
for (ll k=0;k<i;++k)
{
ll x=f[j+k],y=f[i+j+k];
f[j+k]=(x+y)%mod,f[i+j+k]=(x-y+mod)%mod;
if (inv==-1)(f[j+k]*=inv2)%=mod,(f[i+j+k]*=inv2)%=mod;
}
}
FWT搞完
本人版权意识薄弱……
别人早就会的东西我现在才学
(FFT)都会了一年了我才懂(FWT)原因还是我太蔡了