• 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;
    }
    
  • 相关阅读:
    C# Excel工作表区域Range装入数组
    【Word VBA】批量插入图片到表格
    C# Office Com 开发 创建任务窗格 CustomTaskPane
    C# Office Com 开发 Excel插件与函数dll注册
    视频逐帧转换为图片
    ssh 免密登录
    NPS 内网穿透配置
    php7.3 centos Call to undefined function AdminControllermcrypt_get_block_size()
    Centos 6 安装 php7.3.x
    nginx配置之proxy_pass路径加斜杠/以及包含路径的区别
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10766108.html
Copyright © 2020-2023  润新知