Skip to main content

快速沃尔什变换(FWT)

参考资料

实现

分治递归

191 Bcpp
void fmt_or(ll *a,int n,int type)
{
if(n==1)return;
int mid=n>>1;
ll *a0=a,*a1=a+mid;
fmt_or(a0,mid,type);
fmt_or(a1,mid,type);
for(int i=0;i<mid;i++)a1[i]=(a1[i]+a0[i]*type+mod)%mod;
}

倍增迭代

181 Bcpp
void fmt_or(ll *a,int n,int type)
{
for(int k=1;k<n;k<<=1)
{
for(int i=0;i<n;i+=k<<1)
{
for(int j=0;j<k;j++)
{
a[i+j+k]=(a[i+j+k]+a[i+j]*type+mod)%mod;
}
}
}
}

高维前缀和

141 Bcpp
void fmt_or(ll *a,int n,int type)
{
for(int i=1;i<n;i<<=1)
{
for(int j=0;j<n;j++)
{
if(i&j)a[j]=(a[j]+a[i^j]*type+mod)%mod;
}
}
}

例题

给定长度为 2n2^n 的两个序列 A,BA,B,设:

Ck=ij=kAi×BjC_k=\sum_{i\oplus j=k}A_i\times B_j

分别当 \oplusor,and,xor\operatorname{or},\operatorname{and},\operatorname{xor} 时求出 CC

给定两个长度为 2n2^n 的序列 a0,a1,,a2n1a_0,a_1,\dots,a_{2^n-1}b0,b1,,b2n1b_0,b_1,\dots,b_{2^n-1},你需要求出一个序列 c0,c1,,c2n1c_0,c_1,\dots,c_{2^n-1},其中 ckc_k 满足:

ck=i&j=0i  j=kaibjc_k=\sum_{\substack{{i \& j=0}\\{i~\mid~ j=k}}} a_i b_j

其中  ~\mid~表示按位或,&\&表示按位与。

答案对 109+910^9+9 取模。