【算法简介】
FFT/NTT是用来求这样的式子
但是考虑形如这种位运算卷积就需要用到下面的FWT了
我们仍然考虑和FFT一样的思路构造出多项式进行计算
下面我们分以下几种计算
【例题】P4717 【模板】快速莫比乌斯/沃尔什变换 (FMT/FWT)
【代码】
#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define fi first
#define se second
#define lson now<<1
#define rson now<<1|1
typedef long long ll;
const int mod=998244353;
const int maxn=131075;
int a[maxn],n,b[maxn];
int inv2;
int qpow(int a,int b)
{
int res=1;
while(b)
{
if(b&1) res=1LL*res*a%mod;
a=1LL*a*a%mod;
b>>=1;
}
return res;
}
void fwt_or(int *A,int op)
{
for(int i=1;i<n;i<<=1)
for(int P=i<<1,j=0;j<n;j+=P)
for(int k=0;k<i;k++)
{
if(op==1) A[i+j+k]=(A[j+k]+A[j+k+i])%mod;
else A[i+j+k]=(A[j+k+i]+mod-A[j+k])%mod;
}
}
void fwt_and(int *A,int op)
{
for(int i=1;i<n;i<<=1)
for(int P=i<<1,j=0;j<n;j+=P)
for(int k=0;k<i;k++)
{
if(op==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 op)
{
for(int i=1;i<n;i<<=1)
for(int P=i<<1,j=0;j<n;j+=P)
for(int k=0;k<i;k++)
{
int x=A[j+k],y=A[j+k+i];
A[j+k]=(x+y)%mod; A[j+k+i]=(x+mod-y)%mod;
if(op==-1)
A[j+k]=1LL*A[j+k]*inv2%mod,A[j+k+i]=1LL*A[j+k+i]*inv2%mod;
}
}
int c[maxn],d[maxn];
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d",&n);
n=qpow(2,n); inv2=qpow(2,mod-2);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=0;i<n;i++) scanf("%d",&b[i]);
for(int i=0;i<n;i++) c[i]=a[i],d[i]=b[i];
fwt_or(c,1); fwt_or(d,1);
for(int i=0;i<n;i++)
c[i]=1LL*c[i]*d[i]%mod;
fwt_or(c,-1);
for(int i=0;i<n;i++) printf("%d ",c[i]);
printf("\n");
for(int i=0;i<n;i++) c[i]=a[i],d[i]=b[i];
fwt_and(c,1); fwt_and(d,1);
for(int i=0;i<n;i++)
c[i]=1LL*c[i]*d[i]%mod;
fwt_and(c,-1);
for(int i=0;i<n;i++) printf("%d ",c[i]);
printf("\n");
for(int i=0;i<n;i++) c[i]=a[i],d[i]=b[i];
fwt_xor(c,1); fwt_xor(d,1);
for(int i=0;i<n;i++)
c[i]=1LL*c[i]*d[i]%mod;
fwt_xor(c,-1);
for(int i=0;i<n;i++) printf("%d ",c[i]);
return 0;
}