思路
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;
}