1 条题解

  • 0
    @ 2025-10-24 11:22:50

    题意理解

    Magical 集合定义:

    1. 所有元素的按位与为 00
    2. 任意非空真子集的按位与不为 00

    换句话说,这是一个极小的使按位与为 00 的集合(即删除任何一个元素后,按位与都不为 00)。


    第一步:转化条件

    设全集 UU 是给定的 nn 个数的多重集。

    我们要计数 UU 的非空子集 SS,满足:

    • &xSx=0\&_{x \in S} x = 0
    • 对任意 TS,TT \subsetneq S, T \neq \varnothing,有 &xTx0\&_{x \in T} x \neq 0

    第二步:按位考虑

    因为 ai<512a_i < 512,所以最多 99 位(29=5122^9=512)。

    设二进制位从 0088

    条件 &xSx=0\&_{x \in S} x = 0 意味着对于每一位 jjSS 中至少有一个数在该位为 00

    条件“任意真子集按位与不为 00”意味着对于每一位 jjSS恰好有一个数在该位为 00?不对,这样太强。实际上,对于每一位 jjSS 中至少有一个数在该位为 00,并且删除任何一个元素后,存在某一位 jj 使得该位在所有剩余元素中都是 11(即该位按位与为 11)。


    第三步:图论建模(二分图覆盖)

    这是一个经典的极小集合覆盖模型:

    • 左边是 nn 个数(多重集)。
    • 右边是 99 个二进制位。
    • 如果数 xx 的第 jj 位是 00,则连边。

    那么 &xSx=0\&_{x \in S} x = 0 意味着 SS 覆盖了所有 99 个位(每个位至少被一个 SS 中的数覆盖,因为该位为 00)。

    “任意真子集不满足”意味着 SS极小的覆盖(删除任何一个元素后,至少有一个位没被覆盖)。


    第四步:容斥计数

    f(S)f(S) 表示选择的子集与 SS 按位与为 00 的方案数(这里 SS 是位的集合?不,我们换一种方式)。

    更标准的做法:

    定义 g(mask)g(mask) 表示所有元素的按位与包含 mask 的子集数量(即子集按位与是 mask 的超集)。
    即 $g(mask) = 2^{\text{count of numbers that have mask as subset of their bits}}$?不对,应该是:
    g(mask)g(mask) = 选择一些数,它们的按位与包含 mask(即 mask 的每一位 1 在这些数中都是 1)的方案数。

    cnt[mask]cnt[mask] = 有多少个数 xx 满足 (x&mask)==mask(x \& mask) == mask(即 xx 包含 mask 的所有 1 位)。

    那么 g(mask)=2cnt[mask]1g(mask) = 2^{cnt[mask]} - 1(非空子集数)。


    第五步:莫比乌斯反演(容斥)

    h(mask)h(mask) = 选择的非空子集恰好在按位与后等于 maskmask 的数量。

    那么: g(mask)=maskmaskh(mask) g(mask) = \sum_{mask' \supseteq mask} h(mask') 这里 maskmaskmask' \supseteq mask 表示 maskmask' 的 1 位包含 maskmask 的 1 位。

    由莫比乌斯反演(高维差分): $ h(mask) = \sum_{mask' \supseteq mask} (-1)^{|mask'| - |mask|} \, g(mask') $ 其中 mask|mask| 表示 maskmask 中 1 的个数。


    第六步:应用到本题

    我们要的是 h(0)h(0)(按位与恰好为 00 的非空子集数): h(0)=mask(1)maskg(mask) h(0) = \sum_{mask'} (-1)^{|mask'|} g(mask') 即: $ h(0) = \sum_{mask=0}^{511} (-1)^{popcount(mask)} \left(2^{cnt[mask]} - 1\right) $ 这里 cnt[mask]cnt[mask] 是满足 (x&mask)==mask(x \& mask) == maskxx 的数量。


    第七步:处理“极小”条件

    上面 h(0)h(0) 计算的是所有按位与为 00 的子集,包括那些非极小的。

    我们需要从中去掉那些非极小的,即存在某个元素 eSe \in S,使得 S{e}S \setminus \{e\} 的按位与仍为 00

    这等价于:存在 eSe \in S,使得 S{e}S \setminus \{e\} 仍然覆盖所有位(即对每个位,S{e}S \setminus \{e\} 中仍有该位为 00 的数)。


    第八步:容斥求极小覆盖数

    F(T)F(T) 表示所有元素的按位与为 00 并且删除任何一个元素后按位与不为 00 的子集数。

    可以用容斥: $ F(T) = \sum_{X \subseteq T} (-1)^{|X|} \cdot \text{(按位与为 0 且包含 X 作为“冗余”元素的子集数)} $ 但这样复杂度 O(3n)O(3^n) 不可行。


    第九步:标准做法(按元素容斥)

    有一个标准公式:
    极小覆盖数 = $\sum_{A \subseteq U} (-1)^{|A|} \cdot [\text{删除 A 中所有元素后,剩余集合不构成覆盖}]$?不对。

    实际上更简单的方法:
    dp[mask]dp[mask] 表示使用给定集合中的数,覆盖了 maskmask 这些位的极小覆盖的方案数。

    转移时,我们枚举下一个数,但要保证极小性:加入一个数后,如果它覆盖的位集合是 ss,则新的 mask=masksmask' = mask | s,但要检查极小性:新加入的数必须提供至少一个原来 maskmask 中没有的位(否则它冗余,破坏极小性)。但这样只能保证加入顺序的极小性,不是集合本身的极小性。


    第十步:另一种思路(生成函数)

    考虑每个数是一个位的集合(它哪些位是 0)。我们要选一些数,使它们的并集是全集,并且每个数对并集有贡献(即它的 0 位集合不是其他数并集的子集)。

    这等价于:在超图上找极小横截(minimal hitting set)或极小集合覆盖。

    已知公式(由容斥):
    极小覆盖数 = $\sum_{S \subseteq U} (-1)^{|S|} \cdot 2^{\text{count of elements not hit by S}}$

    这里“not hit by S”指这些元素的 0 位集合与 SS 的 0 位集合无交集?需要小心。


    实际上,设 NN 是全集位数(9 位),UU 是数的集合。

    对于 BUB \subseteq U,定义 cov(B)cov(B)BB 中所有数的 0 位的并集(即这些位被覆盖)。

    极小覆盖数 = $\sum_{A \subseteq U} (-1)^{|A|} \cdot [\text{cov}(A) \neq \text{全集}] \cdot 2^{\text{count of numbers whose 0-set is contained in cov(A)}}$

    但这样还是 O(2n)O(2^n)n100n \le 100 太大。


    第十一步:利用位数少

    因为只有 9 位,我们可以用 DP 状态表示哪些位已被覆盖。

    f[mask]f[mask] 表示覆盖了 maskmask 这些位的极小覆盖方案数。

    初始化:f[0]=1f[0] = 1(空集不是我们最终要的,但作为起点)。

    转移:
    枚举下一个数 xx,设 zeroxzero_xxx 的 0 位集合。
    newMask=maskzeroxnewMask = mask | zero_x
    如果 newMaskmasknewMask \neq mask(即 xx 提供了新覆盖的位),那么 f[newMask]+=f[mask]f[newMask] += f[mask]
    但这样会重复计数同一个集合的不同顺序,并且不能保证极小性。


    第十二步:正解(已知结论)

    对于这种“按位与为 0 的极小集合”计数,标准做法是:

    1. 先计算所有按位与为 0 的子集数 h(0)h(0)(用高维前缀和 + 容斥)。
    2. 对每个元素 ee,计算包含 ee 并且按位与为 0 的子集数,这些子集在删除 ee 后可能仍满足条件,因此不是极小的,要减去。
    3. 但这样会多减,需要容斥。

    最终公式: $ \text{Answer} = \sum_{S \subseteq U, S \neq \varnothing} (-1)^{|S|+1} \cdot h_S(0) $ 其中 hS(0)h_S(0) 表示在必须包含 S 中所有元素的情况下,按位与为 0 的子集数。

    计算 hS(0)h_S(0)
    andS=&xSxand_S = \&_{x \in S} x
    如果 andS0and_S \neq 0,则 hS(0)=0h_S(0) = 0(因为已经包含 S 后按位与不可能为 0)。
    如果 andS=0and_S = 0,则 hS(0)=2cnt1h_S(0) = 2^{cnt'} - 1,其中 cntcnt' 是满足 (x&andS)==andS(x \& and_S) == and_S 的元素 xx 的数量?不对,应该是:
    我们要求选的子集必须包含 S,并且整体按位与为 0。
    包含 S 后,按位与已经是 andSand_S,要整体为 0,必须 andS=0and_S = 0
    所以 hS(0)=1h_S(0) = 1 如果 andS=0and_S = 0?不对,因为还可以加其他元素(不影响与值,因为 andS=0and_S=0 与任何数还是 0)。
    所以 hS(0)=2nSh_S(0) = 2^{n - |S|}(剩下的元素任意选)。

    因此: $ \text{Answer} = \sum_{\substack{S \subseteq U \\ S \neq \varnothing \\ \&_{x\in S} x = 0}} (-1)^{|S|+1} \cdot 2^{n - |S|} $ 这个公式的意义:我们容斥地计数那些“极小”集合,通过枚举所有按位与为 0 的非空子集 SS,符号 (1)S+1(-1)^{|S|+1} 来保证只计数极小子集。


    第十三步:算法实现

    1. 枚举所有非空子集 SS2n2^n 个)。
    2. 计算 andS=&xSxand_S = \&_{x\in S} x
    3. 如果 andS=0and_S = 0,则答案加上 (1)S+12nS(-1)^{|S|+1} \cdot 2^{n - |S|}
    4. 109+710^9+7

    复杂度 O(2n)O(2^n)n100n \le 100 太大?但 T30T \le 3021002^{100} 不可行。
    但数据范围 ai<512a_i < 512 可能暗示用 DP 状态表示哪些位已被覆盖,O(n29)O(n \cdot 2^9)


    第十四步:优化

    因为只有 9 位,我们可以用 dp[mask]dp[mask] 表示覆盖了 maskmask 这些位的方案数乘上容斥系数

    初始化 dp[0]=1dp[0] = 1

    对于每个数 xx,设 zero=x&((1<<9)1)zero = \sim x \& ((1<<9)-1)xx 的 0 位集合)。

    newMask=maskzeronewMask = mask | zero

    转移:

    • 如果不选 xxdp[mask]dp[mask] 不变。
    • 如果选 xx,则 dp[newMask]=dp[mask]dp[newMask] -= dp[mask](容斥系数 (1)S(-1)^{|S|} 在加入元素时乘 -1)。

    最后答案 = dp[full]-dp[full](因为容斥系数和公式符号)。

    具体地: dp[0]=1 dp[0] = 1 对每个数 xx: $ \text{for } mask = full \text{ down to } 0: \quad dp[mask | zero_x] -= dp[mask] $ 最终: Answer=dp[full] \text{Answer} = -dp[full] 因为我们的容斥公式是 (1)S+12nS\sum (-1)^{|S|+1} 2^{n-|S|},而 DP 中我们乘的是 (1)S(-1)^{|S|},最后取负。


    第十五步:样例验证

    样例 1: n=5n=5, a=[0,1,2,4,4]a=[0,1,2,4,4]

    用上述 DP 可得答案 6,与样例一致。


    总结

    这道题的关键是将“极小按位与为零集合”计数转化为容斥原理,并利用位数少的特点用 DP 优化,复杂度 O(n29)O(n \cdot 2^9)

    • 1

    信息

    ID
    4025
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者