题目大意
初始有两个数 (a,b) ,有 (n) 次操作,每次提供一个数 (a_i) ,要么不操作,要么从 (a,b) 中选一个数异或上 (a_i) ,问最后 (a,b) 相同的方案数。
(n,a_ile 10^6)
思路
不难看出如果我们设 (x=aoplus b) ,那么每次操作就是 (xgets xoplus a_i) ,于是我们可以想到使用 ( exttt{FWT}) 解决这个问题。我们发现最后的答案其实就是:
[[x^0]igoplus_{i=1}^{n}(1+2x^{a_i})-1
]
(减 (1) 是因为题目要求不能不操作,尽管这显得非常多此一举)
然后我们就发现直接 ( exttt{FWT}) 铁定 gg ,然后我们考虑到有值得数位很少,可以联想到 CF1119H Triple ,我们发现 ( exttt{FWT}[i]) 要么为 (-1) 要么为 (3) ,因为 (1) 产生的贡献一定为 (1) ,而 (2x^{a_i}) 产生的贡献一定为 (pm 2) 。
于是,我们的问题就是对于每一位知道有多少个 (3) (因为 (3) 的个数和 (-1) 的个数之和一定为 (n))。我们设这个东西为 (x) ,我们发现如果设
[f_i= exttt{FWT}(sum_{i=1}^{n}(1+2x^{a_i}))[i]
]
那我们就有等式:
[(-x)+3(n-x)=f_i
]
于是我们就可以解出 (x) 了 。然后我们将这个东西带回去,( exttt{IDWT}) 一遍就好了。
时间复杂度 (Theta(nlog^2 n)),假设 (n) 与值域同阶。
( exttt{Code})
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define mod 998244353
#define MAXN 1048576
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
int n,maxf,inv2,inv4,logn,g[MAXN],aa[MAXN],pw[MAXN];
int mul (int a,int b){return 1ll * a * b % mod;}
int dec (int a,int b){return a >= b ? a - b : a + mod - b;}
int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;}
int qkpow (int a,int b){
int res = 1;for (;b;b >>= 1,a = mul (a,a)) if (b & 1) res = mul (res,a);
return res;
}
void FWT (int *f,int n){
for (Int i = 1;i < n;i <<= 1)
for (Int j = 0;j < n;j += i << 1)
for (Int k = 0;k < i;++ k){
int x = f[j + k],y = f[i + j + k];
f[j + k] = add (x,y),f[i + j + k] = dec (x,y);
}
}
void IFWT (int *f,int n){
for (Int i = 1;i < n;i <<= 1)
for (Int j = 0;j < n;j += i << 1)
for (Int k = 0;k < i;++ k){
int x = f[j + k],y = f[i + j + k];
f[j + k] = mul (inv2,add (x,y)),f[i + j + k] = mul (inv2,dec (x,y));
}
}
signed main(){
read (n),pw[0] = 1;
inv2 = qkpow (2,mod - 2),inv4 = qkpow (4,mod - 2);
for (Int i = 1;i <= n;++ i) pw[i] = mul (pw[i - 1],3);
for (Int i = 1,ai;i <= n;++ i) read (ai),g[0] ++,g[ai] += 2,maxf = max (maxf,ai);
while ((1 << logn) <= maxf) logn ++;
FWT (g,1 << logn);
for (Int i = 0;i < 1 << logn;++ i) {
int x = mul (dec (3 * n,g[i]),inv4);
g[i] = mul (x & 1 ? (mod - 1) : 1,pw[n - x]);
}
IFWT (g,1 << logn);
write (dec (g[0],1)),putchar ('
');
return 0;
}