Playing games

题目:
https://ac.nowcoder.com/acm/contest/295/H

有n个数,选出尽量多的数使得异或和为 0 0 0
1 ≤ n ≤ 500000 , 0 ≤ a i ≤ 500000 1\le n\le 500000,0\le a_i\le 500000 1n500000,0ai500000
思路:
问题等价于选出尽量少的数使得异或和为全部数的异或和 v a l val val。根据线性基思想可以推得整个集合的异或集合可以被不超过 19 19 19个数的异或集合表示.因此答案也不超过 19 19 19。所以可以二分答案。
那么如何判断选 m i d mid mid个数能否异或成 v a l val val,可以用生成函数 A = ∑ i = 0 500000 a i x i A=\sum_{i=0}^{500000}a_ix^i A=i=0500000aixi a i = 1 a_i=1 ai=1表示 i i i这个数存在,为 0 0 0表示不存在, A k A^k Ak就表示选 k k k个,只不过这里是多项式的异或,用 F W T FWT FWT,而且算 B = A k B=A^k B=Ak,可以直接算 F W T ( B ) = F W T ( A ) k FWT(B)=FWT(A)^k FWT(B)=FWT(A)k,这样只要把 A A A变成 F W T ( A ) FWT(A) FWT(A),然后对每一位算 k k k次幂,再把 F W T ( B ) FWT(B) FWT(B)变成 B B B就行,类似点值表示法。
还要注意一点,这样会选重复,所以没法直接判断能否刚好选 m i d mid mid个数,但是重复的异或会抵消,相当于选的个数少于 m i d mid mid,因为是二分判断,所以退而求其次,变成判断能否用少于 m i d mid mid个数,那么这样生成函数 a 0 = 1 a_0=1 a0=1,代表可以不选。

总结:
异或的卷积形式和加得到的卷积类似,也可以用生成函数。

猜你喜欢

转载自blog.csdn.net/qq_43520313/article/details/108894744