题目:
https://ac.nowcoder.com/acm/contest/295/H
有
n
n
n个数,选出尽量多的数使得异或和为
0
0
0。
1
≤
n
≤
500000
,
0
≤
a
i
≤
500000
1\le n\le 500000,0\le a_i\le 500000
1≤n≤500000,0≤ai≤500000
思路:
问题等价于选出尽量少的数使得异或和为全部数的异或和
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,代表可以不选。
总结:
异或的卷积形式和加得到的卷积类似,也可以用生成函数。