SoSdp 学习笔记

SoSdp 用来解决这种问题:

对于非负整数 iiKK,定义布尔型二元运算 iKi\subseteq K,可以以下四种等价角度理解:

  • ibitandK=ii \operatorname{bitand} K = ibitand\operatorname{bitand} 是按位与的意思。
  • 同一个二进制位上,ii 的这一位小于等于 KK 的这一位。
  • 同一个二进制位上,KK 这一位为 11,则 ii 这一位可以为 1100KK 这一位为 00,则 ii 这一位只能为 00
  • ii 的所有为 11 的二进制位数集,是 KK 的所有为 11 的二进制位数集的子集。

f(K)=iKaif(K) = \sum_{i \subseteq K} a_i

aa 是一个长度为 2N2^N 的数组,要求对于所有 0K<2N0 \le K < 2^N,算出 f(K)f(K)。上面的 \sum 可以换成其它合并运算。

方法一

对每个 KK,暴力计算 f(K)f(K)。对每个 f(K)f(K),暴力枚举 iiΘ(1)\Theta(1) 判断是否 iKi \subseteq K,累计 f(K)f(K) 的答案。

时间复杂度 Θ(4N)\Theta(4^N)

方法二

事实上,有办法只枚举一个数的二进制子集而不枚举其他数,方法比较简单:

初始令 i=Ki = K,每次令 i(i1)bitandKi \gets (i - 1) \operatorname{bitand} K,直到 i=0i = 0 为止。期间访问到的 ii 都是 KK 的子集。

仍对每个 KK 暴力计算 f(K)f(K),但对每个 f(K)f(K),采用上述方法只枚举其子集。

考虑 KK 的二进制子集数量,不难发现是 2popcount(K)2^{\mathrm{popcount}(K)}。可以证明 K=02N12popcount(K)=3N\sum \limits_{K = 0}^{2^N - 1} 2^{\operatorname{popcount}(K)} = 3^N

因此上述算法的时间复杂度是 Θ(3N)\Theta(3^N)

方法三

是否还可以优化?观察到每个 f(K)f(K) 都是由不超过 2N2^Naia_i 构成,每个 aia_i 只作为一个小单位累积到 f(K)f(K) 还是过于暴力了。

考虑一个边长为 22NN 维超立方体,即一个 NN 维数组 a[2][2][2]...[2][2]

然后把一个数 KK 写成二进制形式,然后填入上面的下标,比如 K=(110)2K = (110)_2N=4N = 4,就可以记作 a[0][1][1][0]

考虑前缀和的定义:a 的前缀和数组 sum 中,有sum[K1][K2][K3]..[Kn] 等于所有满足以下条件的 a[k1][k2][k3]...[kn] 的和:k1K1k_1 \le K_1k2K2k_2 \le K_2k3K3k_3 \le K_3,……,knKnk_n \le K_n

不难发现上面这个条件和二进制子集的某个定义是非常类似的:同一个二进制位上,ii 的这一位小于等于 KK 的这一位。

因此,满足上面这个条件的和,即高维前缀和,与二进制子集的和也是类似的,我们可以类比着做。具体可以看代码。

高维前缀和的复杂度可以做到 Θ(N×2N)\Theta(N \times 2^N)。本做法的复杂度也可以。

注意:维数循环在外层,当前状态循环在里层。

例题

ARC100E Or Plus Max

CF449D Jzzhu and Numbers

posted @   dbxxx  阅读(81)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示