随机化做题记录

随机化

主要是爬山、退火和其他神秘随机化题。

随机化题主要利用的就是用随机的方法获得正确答案的概率很大,于是可以随机化。

爬山和模拟退火的区别就在于爬山不接受劣解,因此有时候要随机起点来增大正确性。

[AGC035D] Add and Remove

思路:直接爬山。

CF852A Digits

题意:给定一个长度为 \(n\) 的很长的数,在一次操作可以在其中放若干个加号隔开它,希望使得三次操作后这个数字变成一个一位数,求任意一种操作方案

思路:朴素的拆法肯定是一位一位地拆,但是可能有特例,例如数字和是289,这样就不能直接一位一位拆。不过这样的情况很少,于是可以考虑随机化,每次随机一位或者两位拆,多做几次就可以了。

CF1854E Game Bundles

题意:给定一个正整数 \(m\le 10^{10}\),请你构造一个数组 \(a\),长度为 \(k\),满足 \(\forall 1\le i\le k\le 60,1\le a_i\le 60\),且恰好存在 \(m\) 个集合 \(S\subset\{1,2,\dots,k\}\)\(\sum\limits_{i\in S}a_i=60\)

思路:神秘随机化题。

直接随机若干个不超过 30 的数直到组成 60 的方案数大于 \(k\),删去最后一个元素后贪心地选取大于 30 的数。

证明的话,可能是因为随出来的序列 \(dp[60-x]\) 类似等比数列,于是正确率大。

CF364D Ghd

题意:定义一个集合的Ghd为 所有大小至少为一半的子集的\(\mathrm{gcd}\) 的最大值。

给定集合\(a\),求\(a\)的Ghd。

思路:随机化大法好!

因为 gcd 一定是期中任意一个数的因数,于是可以想到随机选择若干数,检查他们的因数是否是答案,期望只用 2 次就可以找到。

但是因为检查的复杂度太高,我们最多只能检查 10 个数,而这样正确率不够高,考虑优化这一步的复杂度。

假设我们要算一个数的答案,那么我们从小到大列出因子,然后对于其他数,我们二分出这两个数的 gcd 对应那个因子,最终把所有的因子的次数加起来,这样可以在近似 \(O(n)\) 的时间内检查一个数,于是可以多做几次,正确率就足够了。

CF1198F GCD Groups 2

题意:将 \(n\) 个数分为两组,使每组的 \(\gcd=1\)。输出分组方案或无解信息。

思路:考虑随机化。我们随机一个排列,然后把最短的 \(gcd\) 为 1 的前缀求出来,判断后面的 \(gcd\) 是否为 1 即可。

考虑优化。如果一个数出现了不止一次,那么显然放在两个集合是更优的,可以提前处理出来。

P6982 [NEERC2015] Jump

题意:交互题,你要猜一个长度为 \(n\) 的 01 串,你可以向询问一个 01 串,可以得到是否有 \(n\) 位或者 \(\dfrac{n}{2}\) 位对应相同,要求在 \(n+500\) 次以内问出。

思路:很厉害的随机化思想。

考虑假设我们已经知道了有 \(\dfrac{n}{2}\) 位相同,那么就可以用 \(n\) 次问出每一位是否和第一位相同,把所有取反再问一遍即可。

现在的问题是怎么知道一个有 \(\dfrac{n}{2}\) 位相同的串。答案是:直接随。

每次随出来的概率是 \(\dfrac{\binom{\dfrac{n}{2}}{n}}{2^n}\),那么 499 次以内随出来的概率大概是 0.99997,因此有极大概率是对的。

「JOISC 2014 Day3」JOIOJI

题意:给定字符集为 3 的字符串,求最长的子串满足每个字符出现次数相同。

思路:给每个字符赋随机权值,保证随机权值之和是 0,那么一个区间合法当且仅当这个区间的和是 0,于是用 map 维护即可。

「JOISC 2016 Day1」神经衰弱

题意:交互题。有一个排列 \(p\) 和长为 \(2n\) 的序列,\(1\sim n\) 各出现两次。每次 Filp 操作可以选择两个位置,如果两个位置上的数相同,那么你可以知道这个数,否则你可以知道这两个数中 \(p_i\) 最小的一个。你需要再不超过 \(6n\) 次询问内求出这个序列。

思路:考虑 Filp 一个位置和剩下所有位置,记录每个数作为答案出现的次数,如果是 1 次,那么这个位置的答案就是这个数,否则对于所有出现次数为 2 的数,就是比这个数更好记的数,我们就可以确定这些数。

发现上述过程可以看做是排序的过程,把小于的数去掉,然后在大于的数里面继续排序。但是我们不知道这个数是什么,于是考虑随机化,每次随机一个我们要 Filp 的位置,这样做的期望次数是 \(O(n)\) 的,可以通过。

「JOISC 2017 Day2」Broken Device

题意:通信题。Alice 有一个数 X,她可以向 Bob 传一个长度不超过 150 的 01 串,但是其中有 \(k\) 位会被破坏,变成 0,Bob 需要求出 X。

思路:考虑把原序列每两个为一段,然后用三进制数来表示,这样最多可以传 \(3^{\frac{150-40}{2}}=5\times 10^{16}\) 的数。

考虑随机化。我们把两个人手上的序列随机打乱,这样就可以有更多的位置来用。但是还是过不去。

考虑怎么优化。假设一个段只有一个位置可以用,而且刚好可以表示出我们要表示的数,这样就可以利用上非法位置。加上优化后就可以通过了。

其实还可以再优化,就是把三进制下每一位再随机一次。

「JOISC 2018 Day 2」路网服务

题意:提交答案题。有一棵树,你可以额外添加 \(k\) 条边,使得所有点对之间的距离尽量小。

思路:容易想到这 \(k\) 条边一定是连成菊花图,那么就可以考虑爬山。

我们每次先选定中心点 \(rt\),然后枚举选择与哪些点相连,但是估价函数是 \(O(n^2)\) 的,很耗时,那么不妨改成 \(\sum dis(rt,i)\)

对于初始态,可以对枚举每个点作为中心点,然后按度数从大到小选取作为初始状态,选择较小的几组即可。

「JOISC 2020 Day1」汉堡肉

题意:平面上有 \(n\) 个矩形,你可以额外选择 \(k\) 个点,使得每个矩形内至少有一个点。

思路:随机交换。

具体地,我们选择前 \(k\) 个矩形当做特殊矩形,表示我们钦定这 \(k\) 个矩形内有签子,然后我们枚举其他的矩形,选择交的面积占比最大的一个特殊矩形,然后把这两个矩形求交。如果找不到,就随机与前面的一个矩形交换,这样可以在之后更早处理这个矩形,更快找到答案。

CF1556H DIY Tree

题意:有一张无向完全图,需要求出一棵生成树使得每个点的度数不超过 \(d_i\)

思路:正解是用拟阵,但是有随机化贪心乱搞过去了。

定义一棵生成树 \(T\) 的估价函数 \(f(T)\) 表示 \(\sum\max(0,dT_i-d_i)\)。我们考虑先求出最小生成树,然后每次选择一条边权最大且删去后会减小 \(f(T)\),加上一条边权最小且加入不会增大 \(f(T)\) 的边,这样每次都会减小 \(f(T)\),而一次的复杂度是 \(O(n^2)\) 的,因此这样的复杂度是 \(O(n^3)\) 的。

然后考虑加入随机化。选择删掉的边时,如果删去后 \(f\) 会减小,就以 \(\dfrac{3}{4}\) 的概率选择;选择加入的边时,也以 \(\dfrac{3}{4}\) 的概率选择。

发现还是过不去,因为我们每次都会让 \(f(T)\) 减小,但是有时候替换可能会让 \(f(T)\) 不变,但是有利于后面的选择,因此我们需要考虑这类操作。但是我们也不能进行太多这样的操作,于是继续随机化,记一个 \(cnt\),每次替换后让 \(cnt+1\),如果 \(cnt\) 是偶数就有 \(\dfrac{1}{4}\) 的概率进行这样的操作,这样就可过了。

最后要加上卡时。

posted @ 2024-02-13 21:49  Xttttr  阅读(5)  评论(0编辑  收藏  举报