洛谷P4717 -【模板】快速莫比乌斯/沃尔什变换

与:(FWT(A)=(FWT(A_0+A_1),FWT(A_1)))
或:(FWT(A)=(FWT(A_0),FWT(A_0+A_1)))
异或:(FWT(A)=(FWT(A_0+A_1),FWT(A_0-A_1)))

Code

//【模板】快速莫比乌斯/沃尔什变换 (FMT/FWT)
#include <cstdio>
typedef long long lint;
const int P=998244353;
const lint inv2=499122177;
const int N=1<<20;
int n,a[N],b[N],c[N];
void FWT(int x[],int t1,int t2)
{
    for(int i=1;i<(1<<n);i<<=1)
        for(int j=0;j<(1<<n);j+=(i<<1))
            for(int k=0;k<i;k++)
            {
                lint p=x[j+k],q=x[i+j+k];
                if(t1==0) x[i+j+k]=(q+P+t2*p)%P;  //or
                else if(t1==1) x[j+k]=(p+P+t2*q)%P;   //and
                else if(t1==2)   //xor
                {
                    x[j+k]=(p+q)%P*(t2<0?inv2:1)%P;
                    x[i+j+k]=(p+P-q)%P*(t2<0?inv2:1)%P;
                }     
            }
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<(1<<n);i++) scanf("%d",&a[i]);
    for(int i=0;i<(1<<n);i++) scanf("%d",&b[i]);
    for(int t=0;t<3;t++)
    {
        FWT(a,t,1),FWT(b,t,1);
        for(int i=0;i<(1<<n);i++) c[i]=(1LL*a[i]*b[i])%P;
        FWT(a,t,-1),FWT(b,t,-1),FWT(c,t,-1);
        for(int i=0;i<(1<<n);i++) printf("%d%c",c[i],i<(1<<n)-1?' ':'
');
    }
    return 0;
}