模板:快速莫比乌斯变换(FMT)+快速沃尔什变换(FWT)(多项式)

所谓快速沃尔什变换,就是快速的沃尔玛什锦专柜变换

(逃)

前言

正常卷积的定义: c k = ∑ i + j = k a i b j c_k=\sum_{i+j=k}a_ib_j ck=i+j=kaibj
可以用FFT或者NTT在 O ( n log ⁡ n ) O(n\log n) O(nlogn) 的复杂度内解决。
然而,有些时候,我们计算卷积的时候下标关系并不是喜闻乐见的加法,而是形如 c k = ∑ i ⊕ j = k a i b j c_k=\sum_{i\oplus j=k}a_ib_j ck=ij=kaibj,其中的 ⊕ \oplus and or xor 中的一种位运算。
这个时候就需要快速莫比乌斯变换(and or)和快速沃尔什变换(xor),同样可以把复杂度降到 O ( n log ⁡ n ) O(n\log n) O(nlogn) 级别。

解析

由于三个运算思想比较类似,因此不对两个算法进行特别的区分,统称为FWT。
采用类比的思想,FFT先把多项式转化为点值表示,乘到一起,最后再反演回去。
类似的,FWT也是先把多项式 A , B A,B A,B 转化为某种变换 FWT ⁡ ( A ) , FWT ⁡ ( B ) \operatorname{FWT}(A),\operatorname{FWT}(B) FWT(A),FWT(B),然后乘起来得到 FWT ⁡ ( C ) \operatorname{FWT}(C) FWT(C),最后再反演回去得到 C C C
根据不同位运算的性质,对应的变换有所不同。

OR

定义

求: c k = ∑ i ∣ ⁡ j = k a i b j c_k=\sum_{i\operatorname{|}j=k}a_ib_j ck=ij=kaibj
考虑或运算有如下性质:若 i ∣ k = k , j ∣ k = k i|k=k,j|k=k ik=k,jk=k,那么 ( i ∣ j ) ∣ k = k (i|j)|k=k (ij)k=k,反之亦然。
那么我们就按照这个充要条件设计变换: FWT ⁡ o r ( A ) k = ∑ i ∣ k = k A i \operatorname{FWT}_{or}(A)_k=\sum_{i|k=k}A_i FWTor(A)k=ik=kAi
自然语言: i i i 必须是 k k k子集才能转移。
考虑两个变换后的多项式逐项系数相乘
FWT ⁡ o r ( A ) ∗ FWT ⁡ o r ( B ) = ∑ k ( ∑ i ∣ k = k a i ) × ( ∑ j ∣ k = k b j ) \operatorname{FWT}_{or}(A)*\operatorname{FWT}_{or}(B)=\sum_{k}(\sum_{i|k=k}a_i)\times (\sum_{j|k=k}b_j) FWTor(A)FWTor(B)=k(ik=kai)×(jk=kbj)
= ∑ k ∑ i ∣ k = k ∑ j ∣ k = k a i b j = ∑ k ∑ ( i ∣ j ) ∣ k = k a i b j = FWT ⁡ o r ( C ) =\sum_{k}\sum_{i|k=k}\sum_{j|k=k}a_ib_j=\sum_{k}\sum_{(i|j)|k=k}a_ib_j=\operatorname{FWT}_{or}(C) =kik=kjk=kaibj=k(ij)k=kaibj=FWTor(C)
所以我们就证出了系数直接相乘是对的,现在只需要一种快速的变换得到 FWT ⁡ o r \operatorname{FWT}_{or} FWTor 以及将其反演的方法。

变换:

还是和FFT类似的,考虑分治,假设我们要合并两个长度为 2 n 2^n 2n 的序列,设它们不同的最高位为1的序列为 A 1 A_1 A1,为0的为 A 0 A_0 A0
考虑 or的性质, A 0 A_0 A0 可以转移到 A 1 A_1 A1,而 A 1 A_1 A1 无法转移到 A 0 A_0 A0,因此有:
FWT ⁡ o r ( A ) = ( FWT ⁡ o r ( A 0 ) , FWT ⁡ o r ( A 0 ) + FWT ⁡ o r ( A 1 ) ) \operatorname{FWT}_{or}(A)=(\operatorname{FWT}_{or}(A_0),\operatorname{FWT}_{or}(A_0)+\operatorname{FWT}_{or}(A_1)) FWTor(A)=(FWTor(A0),FWTor(A0)+FWTor(A1))
其中 + + + 表示系数逐项相加 ( f ( x ) , g ( x ) ) (f(x),g(x)) (f(x),g(x)) 表示把 f ( x ) f(x) f(x) g ( x ) g(x) g(x) 顺次写出。

逆变换

那么对应的,还原成原序列只需要逆向操作即可:
UFWT ⁡ o r ( A ) = ( UFWT ⁡ o r ( A 0 ) , UFWT ⁡ o r ( A 0 ) − UFWT ⁡ o r ( A 1 ) ) \operatorname{UFWT}_{or}(A)=(\operatorname{UFWT}_{or}(A_0),\operatorname{UFWT}_{or}(A_0)-\operatorname{UFWT}_{or}(A_1)) UFWTor(A)=(UFWTor(A0),UFWTor(A0)UFWTor(A1))

代码

写起来非常简洁:

void Or(ll *x,int n,int op){
  for(int l=1;l<n;l<<=1){
    for(int st=0;st<n;st+=l*2){
      for(int i=0;i<l;i++){
		ll u=x[st+i],v=x[st+l+i];
		if(op==1) x[st+i]=u,x[st+l+i]=(v+u)%mod;
		else x[st+i]=u,x[st+l+i]=(v+mod-u)%mod;
      }
    }
  }
}

AND

or 的整个定义、证明几乎都是一样的。
求: c k = ∑ i & ⁡ j = k a i b j c_k=\sum_{i\operatorname{\&}j=k}a_ib_j ck=i&j=kaibj
与运算有如下性质:若 i & k = k , j & k = k i\&k=k,j\&k=k i&k=k,j&k=k,那么 ( i & j ) & k = k (i\&j)\&k=k (i&j)&k=k,反之亦然。
按照这个充要条件设计变换: FWT ⁡ o r ( A ) k = ∑ i ∣ k = k A i \operatorname{FWT}_{or}(A)_k=\sum_{i|k=k}A_i FWTor(A)k=ik=kAi
自然语言: i i i 必须是 k k k超集才能转移。
后面的证明一模一样,变换也可以同理的得到:
FWT ⁡ a n d ( A ) = ( FWT ⁡ a n d ( A 0 ) + FWT ⁡ a n d ( A 1 ) , FWT ⁡ a n d ( A 1 ) ) \operatorname{FWT}_{and}(A)=(\operatorname{FWT}_{and}(A_0)+\operatorname{FWT}_{and}(A_1),\operatorname{FWT}_{and}(A_1)) FWTand(A)=(FWTand(A0)+FWTand(A1),FWTand(A1))
UFWT ⁡ a n d ( A ) = ( UFWT ⁡ a n d ( A 0 ) − UFWT ⁡ a n d ( A 1 ) , UFWT ⁡ a n d ( A 1 ) ) \operatorname{UFWT}_{and}(A)=(\operatorname{UFWT}_{and}(A_0)-\operatorname{UFWT}_{and}(A_1),\operatorname{UFWT}_{and}(A_1)) UFWTand(A)=(UFWTand(A0)UFWTand(A1),UFWTand(A1))

代码

void And(ll *x,int n,int op){
  for(int l=1;l<n;l<<=1){
    for(int st=0;st<n;st+=l*2){
      for(int i=0;i<l;i++){
		ll u=x[st+i],v=x[st+l+i];
		if(op==1) x[st+i]=(u+v)%mod,x[st+l+i]=v;
		else x[st+i]=(u+mod-v)%mod,x[st+l+i]=v;
      }
    }
  }
}

XOR

这个和之前的有所不同。

定义

求: c k = ∑ i ⊕ ⁡ j = k a i b j c_k=\sum_{i\operatorname{\oplus}j=k}a_ib_j ck=ij=kaibj
d ( x ) d(x) d(x) 为二进制下 x x x 的1的个数的奇偶性(模2的结果)。
有性质: d ( i & k ) ⊕ d ( j & k ) = d ( ( i ⊕ j ) & k ) d(i\& k)\oplus d(j\& k)=d((i\oplus j)\& k) d(i&k)d(j&k)=d((ij)&k)
证明:
由于与运算,只考虑 k k k 为1的那些位。如果某一位 i , j i,j i,j 都是1或0,那么等号两边的奇偶性都不改变;如果某一位 i , j i,j i,j 一个是1一个是0,那么等号两边的奇偶性都改变;所以等号两遍的奇偶性始终同步改变,最后就一定是相等的。

设计:
FWT ⁡ x o r ( A ) k = ∑ i ( − 1 ) d ( i & k ) a i \operatorname{FWT}_{xor}(A)_k=\sum_{i} (-1)^{d(i\& k)}a_i FWTxor(A)k=i(1)d(i&k)ai
那么还是尝试逐项相乘:
FWT ⁡ x o r ( A ) ∗ FWT ⁡ x o r ( B ) = ∑ k ( ∑ i ( − 1 ) d ( i & k ) a i ) × ( ∑ j ( − 1 ) d ( j & k ) b j ) \operatorname{FWT}_{xor}(A)*\operatorname{FWT}_{xor}(B)=\sum_k(\sum_{i} (-1)^{d(i\& k)}a_i)\times (\sum_{j} (-1)^{d(j\& k)}b_j) FWTxor(A)FWTxor(B)=k(i(1)d(i&k)ai)×(j(1)d(j&k)bj)
= ∑ k ∑ i , j ( − 1 ) d ( i & k ) + d ( j & k ) a i b j = ∑ k ∑ i , j ( − 1 ) d ( i & k ) ⊕ d ( j & k ) a i b j =\sum_k\sum_{i,j} (-1)^{d(i\& k)+d(j\& k)}a_ib_j=\sum_k\sum_{i,j} (-1)^{d(i\& k)\oplus d(j\& k)}a_ib_j =ki,j(1)d(i&k)+d(j&k)aibj=ki,j(1)d(i&k)d(j&k)aibj
= ∑ k ∑ i , j ( − 1 ) d ( ( i ⊕ j ) & k ) a i b j = FWT ⁡ x o r ( C ) =\sum_k\sum_{i,j} (-1)^{d((i\oplus j)\& k)}a_ib_j=\operatorname{FWT}_{xor}(C) =ki,j(1)d((ij)&k)aibj=FWTxor(C)
得证。

变换

还是分治的思想,考虑到增加一位后,只有下标最高位带1的数贡献到了下标最高位带1的位置时,最高位与运算结果为1,1的个数增加一个,奇偶性改变,所有的符号都变为相反。其它的转移都不变。
也就是:
FWT ⁡ x o r ( A ) = ( FWT ⁡ x o r ( A 0 ) + FWT ⁡ x o r ( A 1 ) , FWT ⁡ x o r ( A 0 ) − FWT ⁡ x o r ( A 1 ) ) \operatorname{FWT}_{xor}(A)=(\operatorname{FWT}_{xor}(A_0)+\operatorname{FWT}_{xor}(A_1),\operatorname{FWT}_{xor}(A_0)-\operatorname{FWT}_{xor}(A_1)) FWTxor(A)=(FWTxor(A0)+FWTxor(A1),FWTxor(A0)FWTxor(A1))

逆变换

反过来即可。
FWT ⁡ x o r ( A ) = ( FWT ⁡ x o r ( A 0 ) + FWT ⁡ x o r ( A 1 ) 2 , FWT ⁡ x o r ( A 0 ) − FWT ⁡ x o r ( A 1 ) 2 ) \operatorname{FWT}_{xor}(A)=(\frac{\operatorname{FWT}_{xor}(A_0)+\operatorname{FWT}_{xor}(A_1)}{2},\frac{\operatorname{FWT}_{xor}(A_0)-\operatorname{FWT}_{xor}(A_1)}{2}) FWTxor(A)=(2FWTxor(A0)+FWTxor(A1),2FWTxor(A0)FWTxor(A1))

代码

void Xor(ll *x,int n,int op){
  for(int l=1;l<n;l<<=1){
    for(int st=0;st<n;st+=l*2){
      for(int i=0;i<l;i++){
		ll u=x[st+i],v=x[st+l+i];
		if(op==1) x[st+i]=(u+v)%mod,x[st+l+i]=(u+mod-v)%mod;
		else x[st+i]=(u+v)%mod*499122177%mod,x[st+l+i]=(u+mod-v)%mod*499122177%mod;
      }
    }
  }
}

Thanks for reading!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值