1372 字
7 分钟
Maths (Notebook)
NOTE

notebook/ 路径下的文件均为自己整理的内容,按照知识点类别归纳整理。

异或#

异或运算的性质#

TIP

异或运算(\oplus)的本质是“不进位的二进制加法”。

  1. 归零律与恒等律:AA=0A \oplus A = 0A0=AA \oplus 0 = A

    任何数字与自身异或都会“抵消”归零;任何数字与 00 异或保持不变。这也是异或前缀和能够实现区间查询的根本原因。

  2. 交换律与结合律:AB=BAA \oplus B = B \oplus AA(BC)=(AB)CA \oplus (B \oplus C) = (A \oplus B) \oplus C

    异或的顺序不重要。这意味着在一堆数字中,可以随意改变它们的异或顺序,结果不变。

  3. 方程的同解性:如果 AB=CA \oplus B = C,那么必然有 AC=BA \oplus C = BBC=AB \oplus C = A

    这个性质在解题时经常用于“已知目标求变量”。比如想找一个前缀和 P[l]P[l] 使得 P[r]P[l]=KP[r] \oplus P[l] = K,可以直接转换为寻找 P[l]=P[r]KP[l] = P[r] \oplus K

异或前缀和#

假设有一个任意数组 AA,我们定义它的异或前缀和数组为 SS,其中 S[i]=A[1]A[2]A[i]S[i] = A[1] \oplus A[2] \oplus \dots \oplus A[i],且 S[0]=0S[0] = 0

我们可以 O(1)O(1) 地求区间异或和。任意区间 [L,R][L, R] 的异或和为 S[R]S[L1]S[R] \oplus S[L-1]

推导过程:

S[R]=A[1]A[L1]A[L]A[R]S[R] = A[1] \dots \oplus A[L-1] \oplus A[L] \dots \oplus A[R]

S[L1]=A[1]A[L1]S[L-1] = A[1] \dots \oplus A[L-1]

两者相异或,根据异或的第一条性质,A[1]A[1]A[L1]A[L-1] 被全部抵消,只剩下 A[L]A[R]A[L] \dots \oplus A[R]

连续自然数序列的异或前缀和#

例题:cf edu round 189 - D

现有一自然数序列 0,1,2,30, 1, 2, 3 \dots,设 P(x)=012xP(x) = 0 \oplus 1 \oplus 2 \dots \oplus x

NOTE

注:为了消除边界特判,尽量定义 P(0)=0P(0) = 0

存在一个周期性的规律(模 44 周期):

x0(mod4)    P(x)=xx \equiv 0 \pmod 4 \implies P(x) = x

x1(mod4)    P(x)=1x \equiv 1 \pmod 4 \implies P(x) = 1

x2(mod4)    P(x)=x+1x \equiv 2 \pmod 4 \implies P(x) = x + 1

x3(mod4)    P(x)=0x \equiv 3 \pmod 4 \implies P(x) = 0

推导过程:

观察偶数与其相邻的奇数(如 22334455)。偶数 2k2k 的二进制最后一位是 00,奇数 2k+12k+1 的最后一位是 11。所以 2k(2k+1)=12k \oplus (2k+1) = 1

连续四个数 4k,4k+1,4k+2,4k+34k, 4k+1, 4k+2, 4k+3 相异或,就变成了 (4k(4k+1))(4k+2(4k+3))=11=0(4k \oplus (4k+1)) \oplus (4k+2 \oplus (4k+3)) = 1 \oplus 1 = 0。这就是每 44 个数就是一个“归零”周期的原因。

应用#

with 哈希表#

用于求“异或和等于某个特定值 KK 的子数组个数/最长长度”。

做法:直接遍历数组计算 S[i]S[i]。因为 S[i]S[j1]=K    S[j1]=S[i]KS[i] \oplus S[j-1] = K \implies S[j-1] = S[i] \oplus K,所以我们只需要用一个哈希表记录曾经出现过的 SS 值即可。

with Trie#

用于求“异或和最大/最小的子数组”。

将计算出的每个前缀和 S[i]S[i] 的二进制串(通常补齐 31 位)插入到 01 字典树中。当求以 ii 结尾的最大区间异或和时,就是拿着 S[i]S[i] 在 Trie 树中利用贪心策略寻找与其每一位尽量相反S[j1]S[j-1]

组合数学相关#

允许为空的隔板法#

NOTE

nn 个完全相同的球,放进 mm 个不同的盒子里,允许有的盒子为空,一共有多少种放法?

答案为:(n+m1m1)\binom{n + m - 1}{m - 1},由于组合数的对称性,也等于(n+m1n)\binom{n+m-1}{n}

如果不允许为空(每个盒子至少 1 个),那非常简单:nn 个球排成一排,中间有 n1n-1 个空隙。要把它们分成 mm 份,只需要从这 n1n-1 个空隙里挑出 m1m-1 个位置,插入隔板即可。方案数直接就是 (n1m1)\binom{n-1}{m-1}

但现在允许为空,传统的插板法就失效了,因为你可以把两块隔板插在同一个空隙里,或者插在最边缘。为了解决这个问题,我们使用一种“先借后还”的思想:

Step1 - 人为借球#

既然题目允许盒子是空的,那我们干脆借 mm 个完全相同的虚拟球,然后强行给每个盒子先垫底放进 1 个虚拟球。

现在球的总数变成了:n+mn + m 个。

既然每个盒子都已经有了一个垫底的虚拟球,那么接下来我们在分配时,每个盒子至少都有 1 个球了(即转化为不允许为空的情况)

Step2 - 应用经典插板法#

现在,我们要把这 n+mn + m 个球分成 mm 份(每个盒子至少一份)。

n+mn + m 个球排成一排,它们中间一共有 (n+m)1(n + m) - 1 个空隙。

我们需要将其分成 mm 份,所以只要在这 (n+m1)(n + m - 1) 个空隙中,选出 m1m - 1 个位置插入隔板即可。

方案数为:(n+m1m1)\binom{n + m - 1}{m - 1}

Step3 - 归还借来的球#

分完之后,我们把最初借给每个盒子的那 1 个虚拟球拿走。

如果某个盒子刚才只分到了 1 个虚拟球,拿走之后,它就变成了 0 个球(成功实现了允许为空)。

如果某个盒子分到了 3 个球(1 个虚拟球 + 2 个真实球),拿走虚拟球后,它就剩 2 个真实的球。

这个总的方法数量实际上等于第二步插板的方案数。借与还的操作是逻辑闭环的。

质数与合数相关#

任意奇合数都能拆成:3+2+2++2(n3)/2 个3+\underbrace{2+2+\cdots+2}_{(n-3)/2\text{ 个}} 的形式 (From 牛客练习赛154 A)