UOJios
把问题转化一下,变成有多少个异或和为\(0\)的集合,而后这个集合任意拆分就是答案,因此对于一个大小为\(s\)的集合,其贡献是\(2^s\)。
因而咱们能够弄出若干个\((1+2x^{a_i})\)这样子的多项式,而后异或卷积把它们卷起来就是答案。
根据\(FWT\)异或卷积的理论,若是\(i\)位置有一个\(1\),那么\(FWT\)以后对于\(j\)位置的贡献是\(-1^{pop\_count(i\&j)}\)。
因而\(1\)对于全部位置的贡献都是\(1\),\(2\)对于全部位置的贡献是\(\pm 2\),因此对于每个多项式,其\(FWT\)后的结果不是\(-1\)就是\(3\)。
可是对于每个多项式分别\(FWT\)实在是太过浪费,考虑优化这个过程。
由于咱们最终要求的只是每一个位置上对应的全部值的乘积,每一个位置上不是\(-1\)就是\(3\),那么咱们假设有\(x\)个\(-1\),\(n-x\)个\(3\)。
而后咱们只须要把\(x\)给解出来就好了。
因而对应这两个值咱们要找到一个等式,咱们把全部的多项式加起来而后\(FWT\),这样子第\(i\)位上的值\(f_i\)就是\(n\)个多项式\(FWT\)以后的和。
因而咱们有:\((-1)*x+3*(n-x)=f_i\),很容易就能够把\(x\)解出来。
而后\((-1)^x*3^{n-x}\)就是每一个位置\(FWT\)乘起来以后的值。
把这个数组求出来以后再\(IFWT\)一遍就能够获得答案了。数组
#include<iostream> #include<cstdio> using namespace std; #define MOD 998244353 #define inv2 499122177 #define inv4 748683265 #define MAX 1048576 inline int read() { int x=0;bool t=false;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } int n,a[MAX],pw[MAX]; void FWT(int *P,int opt,int len) { for(int i=1;i<len;i<<=1) for(int j=0,p=i<<1;j<len;j+=p) for(int k=0;k<i;++k) { int X=P[j+k],Y=P[i+j+k]; P[j+k]=(X+Y)%MOD,P[i+j+k]=(X+MOD-Y)%MOD; if(opt==-1)P[j+k]=1ll*P[j+k]*inv2%MOD,P[i+j+k]=1ll*P[i+j+k]*inv2%MOD; } } int main() { n=read(); pw[0]=1;for(int i=1;i<=n;++i)pw[i]=3ll*pw[i-1]%MOD; for(int i=1;i<=n;++i)a[0]+=1,a[read()]+=2; pw[0]=1; FWT(a,1,1048576); for(int i=0;i<1048576;++i) { int p=1ll*(n+n+n+MOD-a[i])*inv4%MOD; a[i]=(p&1)?(MOD-pw[n-p])%MOD:pw[n-p]; } FWT(a,-1,1048576); int ans=(a[0]+MOD-1)%MOD; printf("%d\n",ans); return 0; }