【moban】快速沃尔什变换(FWT)模板
到广州了,好热,阳光好刺眼orz,飞机上颓过去了,趁着等车时间看了看原来一直没看懂的fwt,发现还挺好理解的orz
感性理解一下,具体主要是看的yyb的博客
yyb's fwt
DFT
or
$(x_0,x_1)\rightarrow (x_0,x_0+x_1) $
and
$(x_0,x_1)\rightarrow (x_0+x_1,x_1) $
xor
唯一一个无法直接感性理解的,背下来,先加后减。
$(x_0,x_1)\rightarrow (x_0+x_1,x_0-x_1) $
IDFT
前面背下来,这里就是逆运算了
or
$(x_0,x_1)\rightarrow(x_0,x_1-x_0)$
and
$(x_0,x_1)\rightarrow(x_0-x_1,x_1)$
xor
$(x_0,x_1)\rightarrow((x_0+x_1)/2,(x_0-x_1)/2)$
变换之后就可以进行卷积运算了,和法法塔的方式很像。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
void fwtor(int *a,int s,int dft) {//(a0,a0+a1)
for(int st=1;st<s;st<<=1) {
for(int i=0;i<s;i+=(st<<1)) {
for(int j=i;j<i+st;j++) {
if(dft==1) a[j+st] = add(a[j+st],a[j]);
else a[j+st] = sub(a[j+st],a[j]);
}
}
}
}
void fwtand(int *a,int s,int dft) { //(a0+a1,a1)
for(int st=1;st<s;st<<=1) {
for(int i=0;i<s;i+=(st<<1)) {
for(int j=i;j<i+st;j++) {
if(dft==1) a[j] = add(a[j].a[j+st]);
else a[j] = sub(a[j],a[j+st]);
}
}
}
}
void fwtxor(int *a,int s,int dft) {//(a0+a1,a0-a1)
for(int st=1;st<s;st<<=1) {
for(int i=0;i<s;i+=(st<<1)) {
for(int j=i;j<i+st;j++) {
int x = a[j]; int y = a[j+st];
a[j] = add(x,y); a[j+st] = sub(x,y);
if(dft==-1) a[j]=mul(a[j],inv2),a[j+st]=mul(a[j+st],inv2);
}
}
}
}