UOJ310 黎明前的巧克力(fwt)

UOJ310 黎明前的巧克力(fwt)

题目大意

\(\sum_{xor(S)=0}2^{|S|}\),还是去看原题吧

解题思路

考虑其生成函数

\[\prod (1+2x^{a_i}) \]

最后答案就是 \(x^0\) 的系数

发现对于 \((1+2x^{a_i})\) 做 fwt 的系数只有 -1,3

也就是我们求出最终的点值是由一些 -1 和 3 乘起来的,我们只要知道分别的个数即可,那么有个小技巧,我们直接把它们加起来做 fwt 知道点值的和,通过鸡兔同笼就能直接算出来个数了

代码

#include <queue>
#include <vector>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MP make_pair
#define ll long long
#define fi first
#define se second
using namespace std;

template <typename T>
void read(T &x) {
    x = 0; bool f = 0;
    char c = getchar();
    for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
    for (;isdigit(c);c=getchar()) x=x*10+(c^48);
    if (f) x=-x;
}

template<typename F>
inline void write(F x, char ed = '\n')
{
	static short st[30];short tp=0;
	if(x<0) putchar('-'),x=-x;
	do st[++tp]=x%10,x/=10; while(x);
	while(tp) putchar('0'|st[tp--]);
	putchar(ed);
}

template <typename T>
inline void Mx(T &x, T y) { x < y && (x = y); }

template <typename T>
inline void Mn(T &x, T y) { x > y && (x = y); }

const int P = 998244353;
const int inv2 = (P + 1) / 2;
const int N = 2000005;
int m, n; ll f[N], ans;
void fwt_xor(ll *a, int ty) {
	for (int i = 1;i < m; i <<= 1) 
		for (int j = 0;j < m; j += (i << 1)) 
			for (int k = 0;k < i; k++) {
				ll x = a[j+k], y = a[i+j+k];
				a[j+k] = (x + y) % P;
				a[i+j+k] = (x - y) % P;
			}
}

ll fpw(ll x, ll mi) {
	ll res = 1;
	for (; mi; mi >>= 1, x = x * x % P)
		if (mi & 1) res = res * x % P;
	return res;
}

int main() {
	read(n); 
	for (int i = 1, x;i <= n; i++) 
		read(x), f[0]++, f[x] += 2;
	m = 1 << 20, fwt_xor(f, 1);
	for (int i = 0;i < m; i++) {
		int k = (3 * n - f[i]) / 4;
		f[i] = fpw(3, n - k);
		if (k & 1) f[i] = P - f[i];
		ans += f[i]; ans >= P && (ans -= P);
	}
	write((ans * fpw(m, P - 2) % P + P - 1) % P);
	return 0;
}
posted @ 2020-09-18 12:18  Hs-black  阅读(182)  评论(0编辑  收藏  举报