专栏文章

Random Hash

算法·理论参与者 1已保存评论 2

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
2 条
当前快照
1 份
快照标识符
@miqjhxk2
此快照首次捕获于
2025/12/04 05:49
3 个月前
此快照最后确认于
2025/12/04 05:49
3 个月前
查看原文
模型 11:给定一个长度为 nn 的序列 aa可以有重复元素,问:
  • 1.1. 给定一个子区间 [l,r][l , r],如何判断 [l,r][l , r] 中所有数都出现了偶数次。错误的概率是多少。
  • 2.2. 给定一个子区间 [l,r][l , r]。根据 11,已知区间 [l,r][l , r] 有的元素出现了奇数次, 如何判断 [l,r][l , r]有且仅有 一个数出现了奇数次。错误的概率是多少。
    • 1.1. 给每一个在序列中出现的数 xx 随机地赋上一个 026410 \sim 2^{64} - 1 内的数 cxc_x。考虑到若区间 [l,r][l , r] 的数都出现了偶数次,则区间异或和必然为 00。因此,若区间 [l,r][l , r]cxc_x 的异或和为 00,我们就认为 [l,r][l , r] 的数都出现了偶数次。
    • 1.1. 一个结论:假设有一个集合 AA,里面的元素在 026410 \sim 2^{64} - 1 完全随机,并且 至少存在一个数出现了奇数次,则我们认为 不管集合 AA 有多少个元素AA 内部所有元素的异或和 xx 等于 026410 \sim 2^{64} - 1 内的某一个数 yy 的概率均为 1264\dfrac{1}{2^{64}}(即把所有数异或起来的结果等价于给一个变量 xx 随机赋一个 026410 \sim 2^{64} - 1 的权值)
    • 1.1. 当区间 [l,r][l , r] 有的数出现了奇数次,但区间异或和为 00 时,答案会出错。根据刚才的结论,出错的概率为 1264\dfrac{1}{2^{64}}
    • 2.2. 设区间 [l,r][l , r]cxc_x 的异或和为 sum\text{sum},若 sum\text{sum}序列 cc 中出现,我们就认为区间 [l,r][l , r] 只有一个数出现了奇数次。
    • 2.2. 当区间 [l,r][l , r] 有多个数出现了奇数次且区间异或和 sum\text{sum}c1cnc_1 \sim c_n 中出现过。错误的概率最坏为 n×1264n\times \dfrac{1}{2^{64}}。由于 sum\text{sum} 在原序列中出现的概率就已经很小了,所以我们不需要再去判断 sum\text{sum} 是否在区间 clcrc_l \sim c_r 中出现过
模型 22:给定两个集合 AABB,问:
  • 1.1.AABB 均满足内部 无重复元素 出现,如何判定 AABB 全等。错误的概率是多少。
  • 2.2.AABB 内部均可能 存在重复元素,如何判定 AABB 全等。错误的概率是多少。
    • 1.1.AABB 每一个出现过的数值 xx 赋上一个 026410\sim 2^{64} - 1 的数值 cxc_x。若 AA 所有元素 cxc_x 的异或和 s1s_1 等于 BB 所有元素异或和 s2s_2,则我们认为 AABB 全等。
    • 1.1.AABB 不全等(即存在一个数只在 AA 或者 BB 出现),并且 s1=s2s_1 = s_2 时,会出错。考虑让 AABB 相同元素抵消。这样,对于一个没有被抵消的数 xx,它要么只在 AA 中出现一次,要么只在 BB 中出现一次。因此 s1s_1s2s_2 两个变量就 独立 并且完全在 026410\sim 2^{64} - 1 随机。
    • 2.2. 由于集合内有重复元素,所以异或的方法不管用了(比如 A={2,2}A = \{2 , 2\}B={4,4}B = \{4 , 4\})。考虑令 s1s_1AA 所有元素的 cxc_x 的和,s2s_2BB 所有元素 cxc_x 的和。若有 s1=s2s_1 = s_2,我们认为 AABB 全等。
    • 2.2. 如何计算错误的概率?考虑消去 AABB 公共元素,则 AABB 独立,并且在 026410\sim 2^{64} - 1 内完全随机。则错误的概率为 1264\dfrac{1}{2^{64}}
模型 33:给定一个序列 aa,问:
  • 1.1. 给定一个整数 kk。然后再给 qq 组询问,每次询问给定两个参数 llrr,表示询问区间 [l,r][l , r] 内是否所有数出现次数都是 kk 的倍数。
  • 2.2.qq 组询问,每次询问给定三个参数 llrrkk 表示询问区间 [l,r][l , r] 是否所有数出现次数都是 kk 的倍数。
  • 1.1. 给每一个出现的数 xx 随机赋一个 026410 \sim 2^{64} - 1 内的权值 cxc_x,使得 kk 个相邻的并且相等的 cxc_x 异或和为 00(注意,它们三个在原序列中不一定相邻),这样,若所有数出现次数都是 kk 的倍数,则区间异或和必然为 00,错误的概率为 1264\dfrac{1}{2^{64}}
  • 2.2. 给每一个出现过的数 xx 随机赋一个权值 cxc_x,求出这个区间 cc 值的和 sum\text{sum},若 sum\text{sum} 不是 kk 的倍数,输出 NO。错误的概率最坏为 12\dfrac{1}{2},随机 3030 次,错误的概率最坏为 1230\dfrac{1}{2^{30}}

P4065 [JXOI2017] 颜色


  • 给定一个长度为 nn 的整数序列,每一个数都有一个颜色 aia_i
  • 定义“删除颜色 xx” 为把所有的满足 ai=xa_i = xaia_i 删掉。问有多少种删除颜色的方案,使得最后剩下的数形成原序列的一个子区间。
  • 例如,假设 aa 初始为 {1,2,3,2,2}\{1 ,2 ,3 ,2 ,2\},若删掉颜色 33,则变为 {1,2}\{1,2\}{2,2}\{2, 2\},不是一个子区间;若删掉颜色 11,则变为 {2,3,3,2}\{2,3,3,2\},是一个子区间。
  • 两个方案不同当且仅当至少存在一个颜色 ii 只在其中一个方案中被删去。
  • 1n3×1051\leq n \leq 3\times 10^51ain1\leq a_i \leq n
  • [l,r][l , r] 为删除后的子区间,则任意一个在区间 [l,r][l , r] 的颜色 xx,都应该满足:序列中 所有的 颜色 xx 只在 区间 [l,r][l , r] 出现。
  • 考虑给每一个位置 ii 赋一个 026410\sim 2^{64} - 1 范围内的数 cic_i,并且要满足,对于任意一个颜色 xx,所有满足 ai=xa_i = xcic_i 的异或和为 00
  • 而当一个区间 [l,r][l , r] 区间异或和为 00,并不能保证区间 [l,r][l , r] 是合法的。当一个区间 [l,r][l , r] 区间异或和不为 00 时,却 一定 能保证区间 [l,r][l , r] 是非法的。
  • 因此,我们考虑当区间 [l,r][l , r] 异或和为 00 时(即当区间 [l,r][l , r] 不合法但区间异或和为 00 时),出错的概率。
  • 区间不合法意味着存在一个颜色 xx,使得颜色 xx 不只是在区间 [l,r][l , r] 出现。此时我们认为区间 [l,r][l , r] 异或和在 026410\sim 2^{64} - 1 中等概率出现,因此判定一个区间是否和合法区间时,出错率为 1264\dfrac{1}{2^{64}},正确率为 112641 - \dfrac{1}{2^{64}}
  • SiS_i 表示 c1cic_1 \sim c_i 的异或和。则剩下的任务是统计有多少个区间 [l,r][l , r] 使得区间 SrSl1=0S_r \oplus S_{l - 1} = 0Sr=Sl1S_r = S_{l - 1}

S2oj #1497 树


  • 给定一棵 nn 个结点的树,树上每条边有边权
  • 给你 qq 组询问,每次给定 uuvv,问 uvu \rightarrow v 这条路径上的边权是否能重新排列,形成一个回文序列。强制在线。
  • 1n1061\leq n \leq 10^61q2×1071\leq q \leq 2\times 10^7
  • 若一个序列可以形成回文序列,需要满足以下两个条件 之一
    • 1.1. 若序列长度为奇数,则有且仅有一个数出现奇数次。
    • 2.2. 若序列长度为偶数,则不存在一个数出现奇数次。
  • 给每一种边权 xx 随机赋上一个在 026410\sim 2^{64} - 1 的值 cxc_x
  • dud_u 表示 1u1 \sim u 路径上所有 cxc_x 的异或和。
  • 则查询时判定 dudvd_u \oplus d_v 是否等于 00 或者等于某一个在 树的边权 出现过的 cxc_x 即可。
  • 考虑单次查询错误的概率,即当路径上不满足条件 11 和条件 22 时,异或和等于 00 或者某一个 cxc_x 的概率,最坏为 (n+1)×1264(n + 1) \times \dfrac{1}{2^{64}},是一个非常小的数值。

CF869E The Untended Antiquity


  • 给定一个 n×mn \times m 的网格。
  • qq 次操作,每次给定三个参数 opt\text{opt}x1x_1y1y_1x2x_2y2y_2
    • opt=1\text{opt} = 1,表示给以 (x1,y1)(x_1,y_1) 为左上角,(x2,y2)(x_2 , y_2) 为右下角的矩形围上篱笆。
    • opt=2\text{opt} = 2,表示给把以 (x1,y1)(x_1,y_1) 为左上角,(x2,y2)(x_2 , y_2) 为右下角的矩形的篱笆拆掉(保证这个篱笆存在)
    • opt=3\text{opt} = 3,表示查询方格 (x1,y1)(x_1 , y_1) 和方格 (x2,y2)(x_2 , y_2) 是否连通
  • 数据保证任意修建的两个篱笆都不相等,并且对于任意两个篱笆,要么包含,要么完全不相交。
  • 1n,m25001 \leq n, m \leq 25001q1051 \leq q \leq 10^5
  • 考虑如何判定两个方格连通。给每一个篱笆一个编号,设围住 (x1,y1)(x_1 , y_1) 的篱笆集合为 Sx1,y1S_{x_1 , y_1},围住 (x2,y2)(x_2 , y_2) 的篱笆集合为 Sx2,y2S_{x_2 , y_2}。发现若满足 Sx1,y1=Sx2,y2S_{x_1 , y_1} = S_{x_2 , y_2},则 (x1,y1)(x_1 , y_1)(x2,y2)(x_2 , y_2) 连通。
  • 如何判定两个集合全等?考虑给每一个编号(编号记做 ii)的篱笆赋一个 026410\sim 2^{64} - 1 的权值 cic_i。则只需要判断 Sx1,y1S_{x_1 , y_1} 内所有 cic_i 的异或和 v1v_1 是否等于 Sx2,y2S_{x_2 , y_2} 内所有 cic_i 的异或和 v2v_2
  • 如何给一个矩形范围内所有的方格的集合 Sx,yS_{x , y} 都添加上编号 ii?使用二维差分 ++ 二维树状数组即可。

ABC 250E Prefix Equality


  • 给定两个长度为 nn 的数列 aabb
  • qq 组询问,每次询问给定两个参数 iijj,询问 a1aia_1 \sim a_i 排序去重后形成的序列 AA,是否等于 b1bjb_1 \sim b_j 排序去重后形成的序列 BB
  • 1n2×1051\leq n \leq 2\times 10^51q2×1051 \leq q \leq 2\times 10^5
  • 考虑模型 22,给每一个在 aa 或者 bb 出现过的数随机赋一个 026410\sim 2^{64} - 1 的权值。
  • 维护 aa 的异或前缀和 s1[i]s_1[i]bb 的异或前缀和 s2[i]s_2[i]
  • 对于 a[i]a[i],如果存在一个 j<ij < i 使得 aj=a[i]a_j = a[i],则只需令 s1[i]s1[i1]s_1[i] \leftarrow s_1[i - 1] 即可。否则令 s1[i]s1[i1]c[a[i]]s_1[i] \leftarrow s_1[i - 1] \oplus c[a[i]]
  • 最后判定 s1[i]s_1[i]s2[j]s_2[j] 是否相等即可。

CF1418G Three Occurrences


给定一个长度为 nn 的序列 aa
问有多少个子区间满足:所有数都 恰好 出现了 33 次。
1n5×1051 \leq n \leq 5 \times 10^51ain1 \leq a_i \leq n
  • 对于一个区间 [l,r][l , r],若区间 [l,r][l , r] 所有数出现次数恰好为 33 当且仅当:
    • 1.1. 所有数出现次数都 3\leq 3
    • 2.2. 所有数出现次数都是 33 的倍数。
  • 枚举右端点 rr,考虑统计 1r1 \sim r 有多少个 ll 使得区间 [l,r][l , r] 满足条件。
  • 对于 11,枚举 rr 的同时维护最小的 jj,使得当 ll 满足 jlrj \leq l \leq r 时,有 [l,r][l , r] 所有数出现次数不超过 33
  • 给每一个数 xx 随机赋一个 026410\sim 2^{64} - 1 内的权值 cxc_x,使得三个相邻的值相同的 c[a[i]]c[a[i]]c[a[j]]c[a[j]]c[a[k]]c[a[k]] 异或和为 00
  • 然后求出 c[a[i]]c[a[i]] 的前缀异或和 S[i]S[i],即 c[a[1]]c[a[i]]c[a[1]] \sim c[a[i]] 的异或和。
  • 对于一个区间 [l,r][l , r],若满足 S[r]S[l1]=0S[r] \oplus S[l - 1] = 0,即 S[r]=S[l1]S[r] = S[l - 1],则我们认为区间 [l,r][l , r] 所有数的出现次数是 33 的倍数。错误概率为 1264\dfrac{1}{2^{64}}
  • 那么剩下的任务就是对于一个 rr,统计 jrj \sim r 内有多少 ll 使得 S[r]=S[l1]S[r] = S[l - 1],用 std::map 作为桶即可。

P8819 [CSP-S 2022] 星战


  • 给定一张 nn 个点 mm 条边的有向图
  • 给定 qq 个操作,首先给定一个参数 tt 表示操作类型:
    • t=1t = 1,表示摧毁一条边 uvu\rightarrow v,数据保证这条边存在。
    • t=2t = 2,表示摧毁所有指向 uu 的边 vuv \rightarrow u
    • t=3t = 3,表示恢复一条边 uvu \rightarrow v,数据保证 uvu \rightarrow v 这条边已经被摧毁。
    • t=4t = 4,表示恢复 最初 所有指向 uu 的边 vuv \rightarrow u
  • 每次操作后,请判断当前的图是否是一个内向基环树森林。如果是输出 YES,否则输出 NO
  • 1n5×1051\leq n \leq 5\times 10^51q5×1051 \leq q \leq 5\times 10^5
  • 内向基环树森林 \leftrightarrow 所有的点有且仅有一条出边。
  • 最直接的想法是给每一个点 ii 维护一个 cnt[i]\text{cnt}[i] 表示 ii 的出度,每次操作完之后看看所有点的出度是否都是 11。但是对于 t=2t = 2t=4t = 4 就有些棘手了,因为对于所有的 vuv\rightarrow u,我们需要给所有的 vv 执行 cnt[v]cnt[v]1\text{cnt}[v] \leftarrow \text{cnt}[v] - 1 或者 cnt[v]cnt[v]+1\text{cnt}[v] \leftarrow \text{cnt}[v] + 1
  • 发现似乎维护每一个点的入度更方便一些。但入度并不能帮助我们判定一个图到底是否是内向基环树森林。
  • 考虑把每一条边 uvu \rightarrow v 的出点 uu 放到一个多重集合 SS, 然后把 1n1 \sim n 每一个点放到一个多重集合 TT 里。发现如果我们想判定这个图是否是內向基环树森林,我们只需要判定 SSTT 是否全等。
  • 立刻想到模型 22,给每一个点 xx 随机赋一个 026410\sim 2^{64} - 1 范围内的数 cxc_x。设 sum\text{sum} 表示集合 SScxc_x 的和。若要判定 SSTT 是否全等,我们只需要判定是否 sum=i=1nci\text{sum} = \displaystyle \sum_{i = 1}^{n} c_i
  • sus_u 表示所有指向 uu 的点 xxcxc_x 之和。设 dud_u 表示 最初 指向 uu 的点的 xxcxc_x 之和。
    • t=1t = 1,令 sumsumcu\text{sum} \leftarrow \text{sum} - c_usvsvcus_v \leftarrow s_v - c_u
    • t=2t = 2,令 sumsumsu\text{sum} \leftarrow \text{sum} - s_usu=0s_u = 0
    • t=3t = 3,令 sumsum+cu\text{sum} \leftarrow \text{sum} + c_ususv+cus_u \leftarrow s_v + c_u
    • t=4t = 4,令 sumsum+dusu\text{sum} \leftarrow \text{sum} + d_u - s_u

CF1746F Kazaee


给定一个整数序列 aa,有 qq 次操作,每次操作有两种类型:
  • 把某一个位置 ii 的值修改成 xx,即 aixa_i \leftarrow x
  • 给定 llrrkk 三个参数,每次询问是否区间 [l,r][l , r] 的数出现次数都是 kk 的倍数。
  • 1n3×1051 \leq n \leq 3 \times 10^51q3×1051 \leq q \leq 3\times 10^5
  • 给每一个出现过的值 xx 随机赋一个在 023110 \sim 2^{31} - 1 的值 cxc_x。如果所有数在区间 [l,r][l , r] 出现次数都为 kk 的倍数,则区间 [l,r][l , r] 内所有数的和一定为 kk 的倍数!
  • 当区间 [l,r][l , r] 存在一些数出现次数不是 kk 的倍数,而区间和是 kk 的倍数时,答案会出错。感性证明:肯定是 kk 越小,冲突的概率越大,则 kk 最小可以取 22(因为 k=1k = 1 肯定输出 YES);肯定是当区间内只有一种数的时候随机性更强一些。
  • 则设这个数为 xx,以及其出现的次数 cnt\text{cnt},则需要计算 cnt×cxmodk=0\text{cnt} \times c_x \bmod k = 0 的概率。令 cntcntmodk\text{cnt} \leftarrow \text{cnt} \bmod k,再令 cntcntgcd(cnt,k)\text{cnt} \leftarrow \dfrac{\text{cnt}}{\gcd(\text{cnt} , k)}kkgcd(cnt,k)k \leftarrow \dfrac{k}{\gcd(\text{cnt} , k)},最终使得 kkcnt\text{cnt} 互质。则需要满足 cxmodkgcd(cnt,k)=0c_x \bmod \dfrac{k}{\gcd(\text{cnt} , k)} = 0,而由于 cnt<k\text{cnt} < k,则 kgcd(cnt,k)2\dfrac{k}{\gcd(\text{cnt} , k)} \geq 2。由于 cxc_x 纯随机,所以错误的概率最坏是 12\dfrac{1}{2}
  • 重复上述操作 3030 次:给所有值随机赋值,用树状数组或者线段树维护区间 cc 值的和,只要这 3030 次内有 11 次发现区间和不是 kk 的倍数,就可以直接判定本次询问为 NO
  • 错误的概率为区间不满足每一个数出现次数都是 kk 的倍数,但是这 3030 次每次区间和都是 kk 的倍数,概率最坏为 (12)30=1230(\dfrac{1}{2})^{30} = \dfrac{1}{2^{30}},可以接受。
  • 注意每次随机时,不应该直接把 cc 数组设置成 unsigned int 或者 unsigned long long。因为树状数组单点修改时,有可能会加上一个负数,而这两个数据类型是不能表示负数,会自动对 2322^{32} 或者 2642^{64} 取模,而取模之后 mod\bmod kk 就失去了意义。

[ABC367F] Rearrange Query


  • 给定一个长度为 nn 的正整数序列 aabb
  • qq 组询问,每次询问给定两个参数 llrr,问 alara_l \sim a_r 重新排列后是否能等于 blbrb_l \sim b_r
  • 1n2×1051 \leq n \leq 2\times 10^51q2×1051\leq q \leq 2\times 10^51ai,bin1\leq a_i,b_i \leq n
  • alara_l \sim a_r 看做集合 AA,把 blbrb_l \sim b_r 看做集合 BB,则只需判定集合 AA 和 集合 BB 是否相等即可。
  • 由于 AABB 内部可能有重复元素出现,所以用 和哈希 Sum-Hash 而不是异或哈希 Xor-Hash
  • 给每一个在序列 AA 或者 BB 出现的数 xx 随机赋一个 026410 \sim 2^{64} - 1 的数值 cxc_x
  • 则维护 aa 序列 ca1caic_{a_1} \sim c_{a_i} 的和 s1[i]s_1[i],以及 bb 序列 cb1cbic_{b_1} \sim c_{b_i} 的和 s2[i]s_2[i]。查询时,判断 s1[r]s1[l1]s_1[r] - s_1[l - 1]s2[r]s2[l1]s_2[r] - s_2[l - 1] 是否相等即可。
完结撒花!欢迎勘误!

评论

2 条评论,欢迎与作者交流。

正在加载评论...