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

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

题意:

在这里插入图片描述
数据范围 n ≤ 17 n\leq 17 n17

题解:

存个模板

代码:

#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
const int N=(1<<17)+9;
int n,a[N],b[N],c[N],lim,ta[N],tb[N];
int poww(int a,int b,int c){
    int ans=1,base=a;
    while(b){
        if(b&1)ans=1ll*ans*base%c;
        base=1ll*base*base%c;
        b>>=1;
    }
    return ans;
}
int inv2=poww(2,mod-2,mod);
//int inv2=mod+1>>1;
void fwt_or(int *a,int opt){
    for(int i=1;i<lim;i<<=1){
        for(int p=i<<1,j=0;j<lim;j+=p)
            for(int k=0;k<i;++k)
            if(opt==1)a[i+j+k]=(a[j+k]+a[i+j+k])%mod;
            else a[i+j+k]=(a[i+j+k]+mod-a[j+k])%mod;
    }
}
void fwt_and(int *a,int opt){
    for(int i=1;i<lim;i<<=1)
        for(int p=i<<1,j=0;j<lim;j+=p)
        for(int k=0;k<i;++k)
        if(opt==1)a[j+k]=(a[j+k]+a[i+j+k])%mod;
        else a[j+k]=(a[j+k]+mod-a[i+j+k])%mod;
}
void fwt_xor(int *a,int opt){
    for(int i=1;i<lim;i<<=1)
        for(int p=i<<1,j=0;j<lim;j+=p)
    for(int k=0;k<i;++k){
        int x=a[j+k],y=a[i+j+k];
        a[j+k]=(x+y)%mod,a[i+j+k]=(x+mod-y)%mod;
        if(opt==-1)a[j+k]=1ll*a[j+k]*inv2%mod,a[i+j+k]=1ll*a[i+j+k]*inv2%mod;
    }
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n;lim=1<<n;
    for(int i=0;i<lim;i++)cin>>a[i],ta[i]=a[i];
    for(int i=0;i<lim;i++)cin>>b[i],tb[i]=b[i];
    fwt_or(ta,1),fwt_or(tb,1);
    for(int i=0;i<lim;i++)ta[i]=1ll*ta[i]*tb[i]%mod;
    fwt_or(ta,-1);
    for(int i=0;i<lim;i++)cout<<ta[i]<<" ";
    cout<<endl;
    for(int i=0;i<lim;i++)ta[i]=a[i],tb[i]=b[i];
    fwt_and(ta,1),fwt_and(tb,1);
    for(int i=0;i<lim;i++)ta[i]=1ll*ta[i]*tb[i]%mod;
    fwt_and(ta,-1);
    for(int i=0;i<lim;i++)cout<<ta[i]<<" ";
    cout<<endl;
    for(int i=0;i<lim;i++)ta[i]=a[i],tb[i]=b[i];
    fwt_xor(ta,1),fwt_xor(tb,1);
    for(int i=0;i<lim;i++)ta[i]=1ll*ta[i]*tb[i]%mod;
    fwt_xor(ta,-1);
    for(int i=0;i<lim;i++)cout<<ta[i]<<" ";
    cout<<endl;
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值