题解 黎明前的巧克力

题目传送门

题目大意

初始有两个数 (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;
}
原文地址:https://www.cnblogs.com/Dark-Romance/p/13535695.html