CF1119H Triple
传送门
首先一个显然的做法是直接 FWT。
设
由于
由于 FWT 是线性变换,所以
又由于 xor 卷积的变换系数是
为了简便,可以将
考虑如何求
枚举
也就是
注意到,
要求的就转化为
拆括号得:
注意到
于是问题等价于求
设
要求的相当于
于是,我们在
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1.4e5+5,mods=998244353;
int pows(int a,int b){
if(b==0)return 1;
int res=pows(a,b>>1);
res=res*res%mods;
if(b&1)res=res*a%mods;
return res;
}
int n,k,x,y,z,a[N],b[N],c[N],al,f[4][N];
void fwt(int*p,int n,int w00,int w01,int w10,int w11){
for(int mid=1;mid<n;mid<<=1){
for(int i=0;i<n;i+=mid<<1){
for(int j=0;j<mid;j++){
int t0=p[i+j],t1=p[i+j+mid];
p[i+j]=(t0*w00+t1*w10)%mods;
p[i+j+mid]=(t0*w01+t1*w11)%mods;
}
}
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>k>>x>>y>>z;
for(int i=1;i<=n;i++){
cin>>a[i]>>b[i]>>c[i];
b[i]^=a[i];c[i]^=a[i];
al^=a[i];
f[1][b[i]]++;
f[2][c[i]]++;
f[3][b[i]^c[i]]++;
}
fwt(f[1],1<<k,1,1,1,-1);
fwt(f[2],1<<k,1,1,1,-1);
fwt(f[3],1<<k,1,1,1,-1);
for(int i=0;i<(1<<k);i++){
int tmp00=(f[3][i]+f[2][i]+f[1][i]+n)/4,tmp01=(-f[3][i]-f[2][i]+f[1][i]+n)/4,tmp10=(-f[3][i]+f[2][i]-f[1][i]+n)/4,tmp11=(f[3][i]-f[2][i]-f[1][i]+n)/4;
f[0][i]=pows((x+y+z)%mods,tmp00)*pows((x+y-z)%mods,tmp01)%mods*pows((x-y+z)%mods,tmp10)%mods*pows((x-y-z)%mods,tmp11)%mods;
}
fwt(f[0],1<<k,499122177,-499122176,499122177,-499122177);
for(int i=0;i<(1<<k);i++)cout<<(f[0][i^al]%mods+mods)%mods<<" ";
}