P4717 【模板】快速沃尔什变换

思路

FWT的模板

FWT解决这样的卷积

[C_k=sum_{iotimes j=k} A_iB_j ]

(otimes)可能是and,or,xor等位运算

几个式子

FWTand:

[a[k]+=a[k+len] ]

IFWTand:

[a[k]-=a[k+len] ]

FWTor:

[a[k+len]+=a[k] ]

IFWTor:

[a[k+len]-=a[k] ]

FWTxor:

[x=a[k]\ y=a[k+len]\ a[k]=x+y\ a[k+len]=x-y ]

IFWTxor:

[x=a[k]\ y=a[k+len]\ a[k]=frac{x+y}{2}\ a[k+len]=frac{x-y}{2} ]

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int inv2 ,a[140000],b[140000],c[140000],n;
const int MOD = 998244353;
int pow(int a,int b){
    int ans=1;
    while(b){
        if(b&1)
            ans=(1LL*ans*a)%MOD;
        a=(1LL*a*a)%MOD;
        b>>=1;
    }
    return ans;
}
void FWTor(int *a,int n){
    for(int i=2;i<=n;i<<=1){
        int len=i/2;
        for(int j=0;j<n;j+=i)
            for(int k=j;k<j+len;k++)
                a[k+len]=(a[k+len]+a[k])%MOD;
    }
}
void IFWTor(int *a,int n){
    for(int i=2;i<=n;i<<=1){
        int len=i/2;
        for(int j=0;j<n;j+=i)
            for(int k=j;k<j+len;k++)
                a[k+len]=(a[k+len]-a[k]+MOD)%MOD;
    }
}
void FWTand(int *a,int n){
    for(int i=2;i<=n;i<<=1){
        int len=i/2;
        for(int j=0;j<n;j+=i)
            for(int k=j;k<j+len;k++)
                a[k]=(a[k]+a[k+len])%MOD;
    }
}
void IFWTand(int *a,int n){
    for(int i=2;i<=n;i<<=1){
        int len=i/2;
        for(int j=0;j<n;j+=i)
            for(int k=j;k<j+len;k++)
                a[k]=(a[k]-a[k+len]+MOD)%MOD;
    }
}
void FWTxor(int *a,int n){
    for(int i=2;i<=n;i<<=1){
        int len=i/2;
        for(int j=0;j<n;j+=i)
            for(int k=j;k<j+len;k++){
                int x=a[k],y=a[k+len];
                a[k]=(x+y)%MOD;
                a[k+len]=(x-y+MOD)%MOD;
            }
    }
}
void IFWTxor(int *a,int n){
    for(int i=2;i<=n;i<<=1){
        int len=i/2;
        for(int j=0;j<n;j+=i)
            for(int k=j;k<j+len;k++){
                int x=a[k],y=a[k+len];
                a[k]=1LL*(x+y)%MOD*inv2%MOD;
                a[k+len]=1LL*(x-y+MOD)%MOD*inv2%MOD;
            }
    }
}
int main(){
    inv2 = pow(2,MOD-2);
    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]);
    int midlen=1;
    while(midlen<(1<<n))
        midlen<<=1;
    FWTor(a,midlen);
    FWTor(b,midlen);
    for(int i=0;i<midlen;i++)
        c[i]=(1LL*a[i]*b[i])%MOD;
    IFWTor(a,midlen);
    IFWTor(b,midlen);
    IFWTor(c,midlen);
    for(int i=0;i<(1<<n);i++)
        printf("%d ",c[i]);
    printf("
");

    FWTand(a,midlen);
    FWTand(b,midlen);
    for(int i=0;i<midlen;i++)
        c[i]=(1LL*a[i]*b[i])%MOD;
    IFWTand(a,midlen);
    IFWTand(b,midlen);
    IFWTand(c,midlen);
    for(int i=0;i<(1<<n);i++)
        printf("%d ",c[i]);
    printf("
");

    FWTxor(a,midlen);
    FWTxor(b,midlen);
    for(int i=0;i<midlen;i++)
        c[i]=(1LL*a[i]*b[i])%MOD;
    IFWTxor(a,midlen);
    IFWTxor(b,midlen);
    IFWTxor(c,midlen);
    for(int i=0;i<(1<<n);i++)
        printf("%d ",c[i]);
    printf("
");
    return 0;
}
原文地址:https://www.cnblogs.com/dreagonm/p/10766108.html