正题
题目链接:https://www.luogu.com.cn/problem/CF1119H
题目大意
nnn个可重集,第iii个里有xxx个aia_iai,yyy个bib_ibi,zzz个cic_ici。
对于每个t∈[0,2k)t\in[0,2^k)t∈[0,2k)求每个集合里取出一个数使它们异或起来等于ttt的方案数。
解题思路
如果直接nnn个东西FWTFWTFWT起来肯定过不了,我们需要根据每个集合里只有三种数这个性质来优化。
因为是xorxorxor卷积,所以第iii个位置FWTFWTFWT之后对jjj造成的影响是(−1)cnt(i&j)(-1)^{cnt(i\&j)}(−1)cnt(i&j)(其中cnt(x)cnt(x)cnt(x)表示xxx在二进制下111的个数)
那么就有
FWT(Si)=∑i=12k−1(−1)cnt(j&ai)x+(−1)cnt(j&bi)y+(−1)cnt(j&bi)zFWT(S_i)=\sum_{i=1}^{2^k-1}(-1)^{cnt(j\&a_i)}x+(-1)^{cnt(j\& b_i)}y+(-1)^{cnt(j\&b_i)}zFWT(Si)=i=1∑2k−1(−1)cnt(j&ai)x+(−1)cnt(j&bi)y+(−1)cnt(j&bi)z
现在我们就可以单独考虑每个x,y,zx,y,zx,y,z的贡献了,然后每个FWT(Si)[j]FWT(S_i)[j]FWT(Si)[j]有888个状态,为了方便我们缩减一下状态先。
首先我们先让所有的xxx都取到,也就是让所有的bi=bixorai,ci=cixoraib_i=b_i\ xor\ a_i,c_i=c_i\ xor\ a_ibi=bi xor ai,ci=ci xor ai,然后询问答案的时候我们再异或上一个aaa的异或和即可。
现在每个FWT(Si)[j]FWT(S_i)[j]FWT(Si)[j]有444种状态,分别是(x+y+z),(x+y−z),(x−y+z),(x−y−z)(x+y+z),(x+y-z),(x-y+z),(x-y-z)(x+y+z),(x+y−z),(x−y+z),(x−y−z)。定义这些状态数量分别为a1,a2,a3,a4a_1,a_2,a_3,a_4a1,a2,a3,a4
我们先考虑集合iii的每种状态中yyy的影响FiF_iFi,有Fi[k]=cnt(k&ai)F_i[k]=cnt(k\& a_i)Fi[k]=cnt(k&ai),而所有集合的影响和就是∑i=1nFi\sum_{i=1}^nF_i∑i=1nFi。设Gi=IFWT(Fi)G_i=IFWT(F_i)Gi=IFWT(Fi)那么显然有Gi[bi]=1G_i[b_i]=1Gi[bi]=1其他都为000。
然后影响和就是∑i=1nFWT(Gi)=FWT(∑i=1nGi)\sum_{i=1}^nFWT(G_i)=FWT(\sum_{i=1}^nG_i)i=1∑nFWT(Gi)=FWT(i=1∑nGi)
所以直接把GGG都加起来然后FWTFWTFWT就好了,定义yyy的影响为c1c_1c1。
然后再同理搞出zzz和y+zy+zy+z的影响,分别为c2,c3c_2,c_3c2,c3,那么就有方程组
{a1+a2+a3+a4=na1+a2−a3−a4=c1a1−a2+a3−a4=c2a1−a2−a3+a4=c3\left\{\begin{matrix} a_1+a_2+a_3+a_4=n\\ a_1+a_2-a_3-a_4=c_1\\ a_1-a_2+a_3-a_4=c_2\\ a_1-a_2-a_3+a_4=c_3 \end{matrix}\right.⎩⎪⎪⎨⎪⎪⎧a1+a2+a3+a4=na1+a2−a3−a4=c1a1−a2+a3−a4=c2a1−a2−a3+a4=c3
解出来就好了,然后用快速幂算出来F=∏i=1nFWT(Si)F=\prod_{i=1}^nFWT(S_i)F=∏i=1nFWT(Si),求一遍IFWT(F)IFWT(F)IFWT(F)即可。
时间复杂度O(2kk+nlog(x+y+z))O(\ 2^kk+n\log(x+y+z)\ )O( 2kk+nlog(x+y+z) )
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=2e5+10,P=998244353;
const ll inv2=(P+1)/2;
ll n,k,x,y,z,xs;
ll f1[N],f2[N],f3[N],f[N];
ll power(ll x,ll b){ll ans=1;x%=P;while(b){if(b&1)ans=ans*x%P;x=x*x%P;b>>=1;}return ans;
}
void FWT(ll *f,ll n,ll op){for(ll p=2;p<=n;p<<=1)for(ll k=0,len=p>>1;k<n;k+=p)for(ll i=k;i<k+len;i++){ll x=f[i],y=f[i+len];if(op==1){f[i]=x+y;f[i+len]=x-y;}else{f[i]=(x+y)*inv2%P;f[i+len]=(x-y)*inv2%P;}}return;
}
signed main()
{scanf("%lld%lld",&n,&k);k=1<<k;scanf("%lld%lld%lld",&x,&y,&z);for(ll i=1;i<=n;i++){ll a,b,c;scanf("%lld%lld%lld",&a,&b,&c);xs^=a;b^=a;c^=a;f1[b]++;f2[c]++;f3[b^c]++;}FWT(f1,k,1);FWT(f2,k,1);FWT(f3,k,1);for(ll i=0;i<k;i++){ll c1=f1[i],c2=f2[i],c3=f3[i];ll a1,a2,a3,a4;a4=(c3-c1-c2+n)/4;a3=-(c1-n+2ll*a4)/2;a2=-(c2-n+2ll*a4)/2;a1=n-a2-a3-a4;f[i]=power(x+y+z,a1)%P*power(x+y-z,a2)%P;f[i]=f[i]*power(x-y+z,a3)%P*power(x-y-z,a4)%P;}FWT(f,k,-1);for(ll i=0;i<k;i++)printf("%lld ",(f[i^xs]+P)%P);return 0;
}