異或卷積,把一個三元組 \(\{a_i,b_i,c_i\}\) 轉化為 \(F_i[a_i]=x\),\(F_i[b_i]=y\),\(F_i[c_i]=z\) 的冪級數,將 \(\prod\limits_{i=1}^n \text{FWT}(F_i)\) 執行 \(\text{IFWT}\) 即可
考慮從每個冪級數只有 \(3\) 個非零值入手最佳化,設 \(c(i,j)\) 表示異或卷積的變換系數,即 \(\text{FWT}(F_k)[i]=\sum\limits_{i=0}^{m-1} c(i,j) F_k[j]\),構造可得 \(c(i,j)=(-1)^{\text{bitcnt}(i \wedge j)}\),則 \(\text{FWT}(F_k)[i]\) \(=(-1)^{\text{bitcnt}(i\wedge a_k)}x+(-1)^{\text{bitcnt}(i\wedge b_k)}y+(-1)^{\text{bitcnt}(i\wedge c_k)}z\)
令 \(S_i=\prod\limits_{k=1}^n \text{FWT}(F_k)[i]\),考慮對每個 \(S_i\) 求出 \(\text{FWT}(F_k)[i]\) 後的乘積項 \(8\) 種情況的個數,此時利用異或的自反性化簡問題,將每個三元組 \(\{a_i,b_i,c_i\}\) 異或 \(a_i\) 變為 \(\{0,a_i \oplus b_i,a_i\oplus c_i\}\),而最終結果的變化反映到冪級數上就是異或 \(\bigoplus\limits_{i=1}^n a_i\) 的下標對映,令 \(x+y+z\),\(x+y-z\),\(x-y+z\),\(x-y-z\) 這 \(4\) 種情況的方案數為 \(c_i\)
考慮列出 \(4\) 個方程求解 \(c_i\),顯然 \(c_1+c_2+c_3+c_4=n\)
如果僅令 \(F_k[b_k]=1\),有 \(\text{FWT}(F_k)[i]=(-1)^{\text{bitcnt}(i \wedge b_k)}\),根據上式 \(y\) 的符號可得 \(\sum\limits_{i=1}^n \text{FWT}(F_k)[i]=c_1+c_2-c_3-c_4\),而 \(\text{FWT}\) 是線性變化,由 \(\text{FWT}(x+y)=\text{FWT}(x)+\text{FWT}(y)\) 可快速求得原式權值
同理僅令 \(F_k[c_k]=1\) 可得 \(c_1-c_2+c_3-c_4\) 的權值
如果僅令 \(F_k[b_k \oplus c_k]=1\),相當於將以上兩種情況卷積,即 \(\text{FWT}(F_k)[i]=(-1)^{\text{bitcnt}(i \wedge b_k)}(-1)^{\text{bitcnt}(i \wedge c_k)}\),可得 \(c_1-c_2-c_3+c_4\) 的權值,解出後維護出 \(\text{IWFT}(S)\) 即可求出答案
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,a,b,c,w;
ll x,y,z,f[131072],g[131072],h[131072],s[131072];
const int mod=998244353,inv=mod+1>>1;
ll qpow(ll a,ll b){
ll s=1;
for(a=(a%mod+mod)%mod;b;b>>=1,a=a*a%mod) if(b&1) s=s*a%mod;
return s;
}
void fwt(ll *f,ll c){
for(int k=1;k<m;k<<=1){
for(int i=0;i<m;i+=k+k){
for(int j=i;j<i+k;j++){
ll x=f[j],y=f[j+k];
if(c) f[j]=x+y,f[j+k]=x-y;
else f[j]=(x+y)*inv%mod,f[j+k]=(x-y+mod)*inv%mod;
}
}
}
}
int main(){
scanf("%d%d%lld%lld%lld",&n,&m,&x,&y,&z),m=1<<m;
for(int i=1;i<=n;i++) scanf("%d%d%d",&a,&b,&c),w^=a,b^=a,c^=a,f[b]++,g[c]++,h[b^c]++;
fwt(f,1),fwt(g,1),fwt(h,1);
for(int i=0;i<m;i++){
ll c=(n+f[i]+g[i]+h[i])/4;
s[i]=qpow(x+y+z,c)*qpow(x+y-z,(n+f[i]-c*2)/2)%mod*qpow(x-y+z,(n+g[i]-c*2)/2)%mod*qpow(x-y-z,(n+h[i]-c*2)/2)%mod;
}
fwt(s,0);
for(int i=0;i<m;i++) printf("%lld ",s[i^w]);
return 0;
}