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

思路

FWT的模板

FWT解决这样的卷积

\[C_k=\sum_{i\otimes 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("\n");

    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("\n");

    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("\n");
    return 0;
}
posted @ 2019-04-25 07:07  dreagonm  阅读(171)  评论(0编辑  收藏  举报