其他分享
首页 > 其他分享> > 【学习笔记】fwt&&fmt&&子集卷积

【学习笔记】fwt&&fmt&&子集卷积

作者:互联网

FWT

基本思路:将多项式变成点值表达,点值相乘之后再逆变换回来得到特定形式的卷积;

多项式的次数界都为\(2^n\)的形式,\(A_0\)定义为前一半多项式(下标二进制第一位为\(0\)),\(A_1\)同理定义;

\((A,B)\)表示多项式\(A\)和\(B\)的直接拼接,FWT的结果都是一个点值表达,相乘表示点值相乘;

下面这些变换都满足线性,记\(n\)为二进制位数,复杂度:\(O(n\times 2^n)\);

or卷积

void fwt(int*A,int F){
    for(int i=1;i<n;i<<=1)
    for(int j=0;j<n;j+=i<<1)
    for(int k=0;k<i;++k){
        if(~F)A[j+k+i]=(A[j+k+i]+A[j+k])%mod;
        else A[j+k+i]=(A[j+k+i]-A[j+k]+mod)%mod;
    }
}

and卷积

xor卷积

FMT

基本思路:将二进制的每一位看成一维,枚举每一维做前缀和就可以得到集合的前缀和;

直接上代码了......

子集前缀和(= or)

for(int i=0;i<n;++i)
for(int j=1<<i;j<1<<n;++j)
    if(j>>i&1)f[j]+=f[j^(1<<i)];

超集前缀和(= and)

for(int i=0;i<n;++i)
for(int j=(1<<n)-1;j>=1<<i;--j)
    if(j>>i&1)f[j^(1<<i)]+=f[j];

fmt的逆变换只需要将第二维反过来减即可;

优点是代码短,常数小,复杂度也是\(O(n \times 2^n)\)

子集卷积和

标签:int,fmt,times,IFWT,FWT,&&,fwt,oplus,卷积
来源: https://www.cnblogs.com/Paul-Guderian/p/10826888.html