2023.12 做题纪要 #2
感动,居然 12 月还有第二个做题纪要!
2023.12.19
有点太安静了,于是拿耳机听歌写题了(
好像还不错,梦幻联动而且确实挺好听。
P7325 [WC2021] 斐波那契
一开始没看数据范围,以为 \(m\) 很大,想半天然后突然意识到数据范围,呃呃。写了个试试,啥,咋就直接过了。
首先有皮那啥周期,所以循环节是 \(O(m)\) 的,我们只需要考虑这 \(O(m)\) 项里面有没有 \(0\)。
但是状态太多了,你不能 \(O(m^2)\) 枚举所有点对吧。考虑减少点有用数对。
注意到问什么时候有 \(0\),那么我们给整个序列乘一个数这个答案是不变的。那么我们可以考虑乘个逆元把 \(a\) 或者 \(b\) 变成 \(1\)。
但是问题是万一逆元都不存在呢?这时候 \(\gcd(a, b, m) = w > 1\),我们可以把三个值全除以 \(w\) 就行了。容易发现这个操作只需要最开始来一次就够了。
那么每次将 \(a/b\) 变成 \(1\),这样就只剩下 \(O(m)\) 对值了,而不同的模数只有 \(d(m)\) 种,每种模数的状态和就是因数和,于是总复杂度就是 \(O(\sigma(m) \log m)\),\(\log\) 是求逆元的复杂度。
题解做法咋都这么麻烦??
P8354 [SDOI/SXOI2022] 多边形
怎么题单里有个 GF 题。
考虑这个题实际上是加了一些限制的三角剖分,没有限制的三角剖分是卡特兰数 \(C_{n-2}\),而这里的具体限制是:可以将同一边中的多个边合并起来,然后要求同一边之间不能有连边。
合并过程直接枚举合并成几段,然后组合数算一下,那么考虑同一边不能有连边咋整。
考虑容斥,我们以同一边连边的数量容斥,仔细推一下发现我们只用统计只跨过两条边的不合法集合,因为如果有跨过更多边的不合法边,那么这条不合法边里面连的边都是不合法的,而把这个集合内的容斥系数加和等于 \(0\)。
那么问题就是,可以在同一边选若干跨过两条边的不合法边,然后再乘上里面三角剖分的方案数。我们只需要考虑求出每种内部多边形边数的容斥系数之和即可计算答案,而显然每一边的容斥系数是独立的,我们可以先求出每一边然后再分治乘法乘起来。
现在只考虑一边,我们的问题是:现在有 \(n\) 条边,将若干条边缩起来,然后将剩下的边划分成长度为 \(1\) 或 \(2\) 的段,每个 \(2\) 的容斥系数是 \(-1\),对每种段数求所有容斥系数之和。
接下来是互动博客,请选择你的路线:
我们可以把两步操作合起来去做,因为实际上我们可以看做先划分 \(1\) 或 \(2\) 段,然后在中间接着划分缩起来的边,那么设 \(f_{i, 0/1/2}\) 表示第 \(i\) 条边在 \(1\) 段,还是在 \(2\) 段的前一部分或后一部分,可以无脑矩阵快速幂,这里比较有趣的是矩阵快速幂的复杂度是 \(O(n \log n)\) 的而不是两个 \(\log\),因为矩阵没有被取模,这个过程相当于倍增。或者你把 DP 写成更好倍增的形式,都行吧。
哦 dottle 说 9 倍就会 TLE,没事了,其实存在 8 倍的 DP,摆了。
考虑推下式子:先枚举划分成多少段,然后枚举选几段 \(2\),设这边一共有 \(n\) 条边,那么容易发现我们就是要求:
也就是说,我们要求出一个数组 \(f_k = \sum_{i=0}^{n} \binom{n - 1}{n - i} \binom{k}{i - k} (-1)^{i - k}\)。但是我们迎来了 \(i, k - i, i + k\) 三个下标,没法直接卷积了,哈哈!
组合意义的尽头是代数推导。
考虑拿 GF 刻画一下,引入个元 \(x\),将上式写成 \(n-i\) 与 \(i-k\) 的卷积形式,即:
这下长得足够抽象了,请选择你的路线:
大力莽一下,记 \(G_k(x) = (1+x)^{n-1} (1-x)^k\),求个导得:
然后还有 \(G_{k+1}(x) = G_k(x) (1-x)\),所以有 \(g_{k+1,i} = g_{k, i} - g_{k,i-1}\)。
那你要求的是 \(g_{k,n-k}\),你就可以 \(O(n)\) 递推了。
有 \(f_k = [x^n] (1+x)^{n-1} (x-x^2)^k\),拆一下有 \(f_k = \sum_{i=0}^n [x^{n-i}] (1+x)^{n-1} [x^i] (x-x^2)^k\),记 \(g_i = [x^{n-i}] (1+x)^{n-1}\),那么就是 \(f_k = \sum_{i=0}^n g_i [x^i] (x-x^2)^k\)。
转置一下,考虑求 \(g_i = \sum_{k=0}^n f_k [x^i] (x-x^2)^k\) 的算法,发现这就是在求多项式 \(F(x-x^2)\),那么就拆一下,有 \(F(x-x^2) = F(-(x-\frac 12)^2 + \frac 14)\),那么有流程:
- \(F(x) \gets F(x + \frac 14)\);
- \(F(x) \gets F(-x)\);
- \(F(x) \gets F(x^2)\);
- \(F(x) \gets F(x - \frac 12)\)。
于是转置过来做就可以了,复杂度 \(O(n \log n)\)。
因为我第一次学转置原理,所以需要写一下多项式平移咋转置(
首先多项式平移实际上是:
令 \(G(x) = \sum \frac{b^i}{i!} x^i\),那么上述过程可以看做是:
- 将 \(F(x)\) 的各项系数乘 \(i!\);
- \(F(x) \gets F(x) \times^T G(x)\);
- 将 \(F(x)\) 的各项系数除以 \(i!\)。
那么转置就是先除以 \(i!\),然后正常乘一个 \(G(x)\),然后再将系数乘 \(i!\)。
考虑直接大力 GF 表示答案,考虑每一段要不然是一段,要不然是两段拼起来的,一端的系数 GF 就是 \(\frac{w}{1-w} - (\frac{w}{1-w})^2 = \frac{w(1-2w)}{(1-w)^2}\),那么答案 GF 就是 \(\sum_{k\ge 0} x^k [w^n] \left(\frac{w(1-2w)}{(1-w)^2}\right)^k\)。
请选择你的路线:
无所谓,我是无脑选手。把上面的式子直接写成二元 GF 的形式,要求的就是 \([w^n] \frac{1-2x+x^2}{1-(x+2)w+(1+2x)w^2}\),可以无脑 Bostan-Mori 求,每次需要 5 次多项式乘法,10 次 FFT。
妈的 loj 上能卡过去,洛谷卡不过去。
额我怎么常数这么大,dottle 说八次多项式乘法都能过,我八次 FFT 都过不了。
ok 过了。卡常:可以不用倍增去做,因为你中途并用不到系数且不需要截断,所以你只需要开头结尾 FFT 一遍,复杂度仍然是 \(O(n \log n)\),不过 FFT 次数少了就常数小多了。
直接拉反,令 \(u\) 为 \(\frac{w(1-2w)}{(1-w)^2}\) 的复合逆,那么有:
可以直接暴力全家桶求出来,或者 ODE 线性求出来。
你猜哪个是我想出来的。当然是无脑 Bostan-Mori。
2023.12.20
咋看着看着给我把网掐了。现在好了。
卧槽 GD 2.2 发布了,卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽
that's crazy
咋还刚好赶上冬促,robtop 你是懂 deadline 的
ok wtf 最后一个月怎么这么劲爆
好像所有人都在玩致命公司,打算整一个玩玩
P9131 [USACO23FEB] Problem Setting P
简单题。首先肯定状压,朴素想法是考虑每个人的状态,然后枚举下一步每个人的状态,然后乘上一个选这种状态的方案,\(O(3^m)\)。
优化一下,发现瓶颈在于每次都要枚举每个状态的后继状态,我们可以改成跑 \(m\) 轮,每次做一边高维前缀和来转移,这样复杂度 \(O(m^2 2^m)\),可以接受。
P7293 [USACO21JAN] Sum of Distances P
经典漏看重要条件。
首先考虑距离是什么。如果某一时刻 \(t\) 满足在每一张图上都能经过恰好 \(t\) 条边到达 \(u_i\),那么 \((1, 1, \cdots, 1)\) 就可以到达 \((u_1, u_2, \cdots, u_k)\),\((1, 1, \cdots, 1)\) 到 \((u_1, u_2, \cdots, u_k)\) 的最小距离就是所有这样的 \(t\) 中的最小值。
注意到图是无向图,那么当我们在 \(t\) 时刻可以到达 \(u\) 时,在 \(t+2\) 时刻也是可以到达 \(u\) 的,因为可以重复走一条边。那么也就是说,一个点能否在 \(t\) 时刻到达由两个时间决定,一个是路径为奇数的最短路径,一个是路径为偶数的最短路径,这容易 bfs 找出。记两条路径长为 \(\min_0(u)\) 与 \(\min_1(u)\),那么两点之间的距离就是:
我们要求的答案就是这个的求和。这种式子直接求肯定不好求,考虑拆贡献,计算这个距离 \(\ge k\) 的有多少,然后对所有 \(k\) 求和就是答案。这个值 \(\ge k\),即 \(\max_i(\mathrm{min}_0(u_i))\ge k\) 且 \(\max_i(\mathrm{min}_1(u_i))\ge k\),我们可以容斥一下,变成求 \(\max_i(\mathrm{min}_0(u_i)) < k\),\(\max_i(\mathrm{min}_1(u_i)) < k\) 和两者同时 \(<k\) 的方案数,这时候就是所有的 \(\mathrm{min}_0(u_i)\) 或 \(\mathrm{min}_1(u_i)\) 均 \(<k\) 了,这样的方案数就很好求了,于是我们就可以求出答案了。
但是注意到有些点可能 \(\min_0\) 或 \(\min_1\) 等于正无穷,因为它们不可能以奇数或者偶数路径到达,而这会导致可能一些点是不可能到达的,我们不能把这些点计算上,于是考虑将点分成三类,\(\min_0\) 和 \(\min_1\) 都不是正无穷,\(\min_0\) 是正无穷与 \(\min_1\) 是正无穷,我们拿第一类与第二类算一次答案,拿第一类与第三累算一次答案,就不会出现上面的情况,但是会把第一类之间的答案算重,所以再减一次第一类的答案。
2023.12.21
THUPC J 评了个黑,那就当我是第一次场切黑题了😎
哦我刚写完这句话 J 就降紫了。
但是洛谷评测机都能跑过去 B,土豆 OJ 狠狠嘲讽。
后天有 cf 耶,挑战一场 div1+div2 直接掉回 master。
P8275 [USACO22OPEN] 262144 Revisited P
这种题只能是贺了,真的一点也不会 😕
首先有一个显然的区间 DP,然后这个 DP 具有区间单调性所以可以二分找决策点之类的,不过这都不重要。
首先答案肯定是 \(O(V)\) 的,于是可以考虑拆贡献,求答案 \(\ge v\) 的区间有多少。由于 DP 具有单调性,我们可以对每一个左端点 \(l\) 维护一个右端点 \(f_l\) 表示最长的答案小于 \(v\) 的区间为 \([l, f_l)\),这样大于这个区间的所有区间答案就都是 \(\ge v\) 的。
考虑怎么维护这个东西,初始肯定 \(f_l = l\),考虑每次令 \(v \to v + 1\),那么对于每个左端点来说,实际上就是将两个最长的答案小于 \(v\) 的区间拼一块形成一个最长的 \(v\) 的区间,那么可以发现新的右端点实际上就是 \(f_{f_l}\)。由于 \(f_l\) 具有单调性,于是这个正确性显然。于是我们就可以 \(O(nV)\) 求解了。
手模一下这个过程,发现很多时候很多 \(f_l\) 的值是相等的。我们断言:对于所有的 \(v\),这样的连续段不多。
实际上,我们有结论:所有 \(v\) 的极长段的总和为 \(O(n \log n)\)。
证明:
考虑建一棵笛卡尔树,设 \(f(n)\) 为长为 \(n\) 的极长段总和,那么设 \(p\) 为最大值的位置,则有 \(f(n) = f(p - 1) + f(n - p) + val(p)\),其中 \(val(p)\) 是包含 \(p\) 的极长段的数量。
假设 \(2p < n\),那么我们可以知道,包含 \(p\) 的答案为 \(a_p + k\) 的极长段有 \(\min(p, 2^k)\) 个,\(p\) 是因为每个左端点最多只会有一个极长段,\(2^k\) 是因为 \(a_p\) 仅有一个极长段,值每增加 \(1\) 后极长段可能向左或向右延伸,故每个段最后仅会分成两端,所以有 \(2^k\) 段。那么答案就是 \(\sum_{k=0}^{\log V} \min(p, 2^k) = O(p \log \frac{n}{p})\),放缩可得 \(O(p \log \frac np) \le O(\sum_{i=0}^{p-1} \log \frac{n - i}{p - i}) = O(\log \binom{n}{p})\)。
归纳证明,我们有 \(f(n) = O(\log n!) = O(n \log n)\),那么根据上式可得 \(f(n) = f(p - 1) + f(n - p) + O(\log \binom{n}{p}) = O(\log p!) + O(\log (n-p)!) + O(\log \frac{n!}{p!(n-p)!}) = O(\log n!)\),得证。
那么我们只需要想办法维护出这些极长段即可。不同的极长段我们可以直接暴力枚举去维护,这些段的 \(f_l\) 全部相同,所以统一修改为 \(f_{f_l}\) 即可,需要注意进行一次拓展后一些 \(f_l\) 的值可能会相等,需要将这些段去掉,也就是只需要保留 \(f_{l-1} < f_l\) 的段。然后再将所有 \(a_l = v\) 的位置加入段 \([l, l + 1)\) 即可。
但是考虑到有些极长段可能在很多 \(v\) 中都不变,所以直接枚举复杂度可能会出错。注意到,若一段极长段不变,那么这一段的左右端点一定都 \(\ge v\),即 \(\min(a_{l-1}, a_{f_l}) \ge v\),否则一定会改变。具体考虑一次拓展后,如果这个段不是极长段,那么直接删除,均摊复杂度一定正确,如果这个段成为了极长段,如果说 \(\min(a_{l-1}, a_{f_l}) < v\),那么说明我们可以将当前段向左或向右拓展一位成为答案为 \(v\) 的段,此时极长段一定改变,而若 \(\min(a_{l-1}, a_{f_l}) \ge v\) 显然当前段不可能进行拓展,于是一定不变。
于是我们可以将两种情况分开维护,一定改变的段暴力维护复杂度肯定是对的,不变的段答案不会发生改变,直接不考虑即可。等加入段 \([l, l+1)\) 的时候,考虑将不变的段加入当前维护的集合中,而若维护的集合中出现了不变的段再删掉就行了。
P5287 [HNOI2019] JOJO
好蠢的样子,感觉脑子不动了。
首先回溯操作可以建出操作树来实现。
然后现在问题是每次加若干个相同的字符跑 KMP。
对于 \(x=1\) 的部分,每次只加一个字符,那么我们只需要一个不基于均摊的 KMP 即可。建出 fail 树,每个点维护当前点到根的第一个下一个字符为 \(c\) 的节点 \(f_{u, c}\) 即可。
每次加若干个字符我们仍然可以类似的想法去做。考虑 border 是什么样子的,发现对于任意一个前缀的 border,前缀与后缀中除了第一段连续的字母与最后一端连续的字母之外,其它段的长度都是相等的。但是第一段与最后一段并不好考虑。首先我们将最后一段删掉,此时前缀一定包含了若干个整段,而注意到如果这个前缀的 border 不是一个整段,那么这个 border 的下一个字符一定与结尾字符相同,那么这个 border 一定匹配不上,于是我们可以不考虑这样的 border,仅考虑包含整段的 border。也就是说,我们可以把连续段看做一个二元组 \((x, c)\),把这个二元组看做一个字符,我们只用考虑这样的串组成的 border 即可。至于开头段,我们只需要在当前匹配长度为 0 的时候特殊匹配一下即可。
先不考虑复杂度,考虑一个暴力的过程:我们要加入下一段 \((x, c)\) 了,此时我们从当前匹配的最长段开始跳 \(nxt\),直到跳到了某个 border 的下一个字符为 \((x, c)\),我们就可以将当前的 \(nxt\) 设为这个点。同时在跳的过程中,如果某个 border 的下一个字符为 \((y, c)\),那么对于当前串加 \([1, y]\) 个 \(c\) 的前缀,它们的 border 就都是这个 border 加若干个 \(c\) 了,于是可以在跳的过程中维护出这些东西。如果没有回溯操作,上述均摊都是线性的,于是可以拿到 80 分了。
回溯就和 \(x=1\) 思路一样,上两棵主席树维护这两个东西就行了。找到最后一个 \((x,c)\) 是显然的,维护答案的话,发现答案只与下一个加的字符是啥有关,于是直接对每个字符维护这个点到根的答案即可。
好像可以使用 border 理论智慧做,摆了。
P6630 [ZJOI2020] 传统艺能
期望的线性性,考虑每个点是否有标记。
那么对于线段树上每一个节点,其实它只关心这个节点有没有标记与它到根上有没有节点有标记。然后分类讨论一下区间的选取方式,有些会将根链上的标记下放到这个节点上,有些会把这个节点标记,有些会把这个节点的标记下放,大概有四种状态,矩阵快速幂一下即可计算出被标记的概率,然后加和就行了。
2023.12.22
喵喵说让我做做沈老师的杂题,说有些是给我找的。
ummm,《我们扔进 To-do List #3 吧》。
thupc 群:(让作弊的主动申诉)怎么还有人申诉的题和我们查到的题不一样的
咋还没出晋级线,虽然我也晋不了级。
我还是想先把我这个题单做完再做别的 一个题单一直拖着很难受(
P8078 [WC2022] 秃子酋长
挺简单的,不过还是少用 STL,第一发 TLE 95 分(
首先这个东西看着就很莫队,直接扔个莫队上去啊,可以 \(O(n \sqrt{n} \log n)\) 了。
然后考虑怎么去 \(\log\)。注意到我们要维护前驱后继信息,删除是容易删除的,我们可以使用链表来维护,而插入是不好插入的。所以我们可以上个回滚莫队,只不过把所有数全加入,按照右端点从右到左依次删除每个数,然后就可以 \(O(n \sqrt{n})\) 了。
正解是分治?咕咕咕。
P9340 [JOISC 2023 Day3] Tourism
这两题放在了一块还是挺搞笑的,因为这两题做法是一模一样的(
考虑经典的转换,按照 dfs 序排序,然后连通块大小就是按顺序距离之和 / 2,然后就和上一题基本一样了。
P8367 [LNOI2022] 盒
还是组合意义好,gf 推半天啥都没推出来。嘲讽 gf。
显然答案等于每个 \(a\) 与 \(b\) 前缀和的差的绝对值乘 \(w_i\),直接拆贡献考虑每个边的贡献,插板法一下容易得到答案为:
考虑拆掉绝对值,我们先只考虑 \(j \le p_i\) 的部分,另一部分把整个序列翻转过来再做一遍就行了。
那么问题就是要求以下两个式子:
如果上界到 \(s\) 是可以做的,但是任意一个前缀和看起来就不像是能做的了,那么我们考虑一下递推。我们只需要每次让上界加 \(1\) 或者让 \(i\) 加 \(1\),快速维护出这两个式子的值即可。上界加 \(1\) 好说,但是 \(i\) 加 \(1\) 看起来有点诡异了,直接作差好像也并不是很好看。
考虑组合意义。上式子可以看做是格路计数,我们可以看做是枚举点 \(j\),然后经过了一条 \((0, 0) \to (j, i - 1) \to (j, i) \to (s, n - 1)\) 的路径,也就是说计数所有在 \(x \le p_i\) 之前穿过 \(y=i - 1\) 的路径数,发现这与不在 \(y \le i - 1\) 之前穿过 \(x = p_i\) 的路径数是相等的。我们设 \(f(p, q, n, m)\) 表示 \((0, 0) \to (j, q - 1) \to (j, q) \to (n, m)\) 且 \(j \le p\) 的路径数,那么有:
于是容易发现递推式:
于是一开始的问题就解决了,我们可以在 \(O(n + s)\) 的复杂度内求出所有的 \(A_i = f(p_i, i, s, n - 1)\)。
那么 \(B_i\) 怎么计算呢?考虑把 \(j\) 吸收进去,由于 \(\binom{j+i-1}{j} j = \binom{j+i-1}{i} i\),于是我们可以把 \(j\) 吸收进去,然后通过类似的推导,容易得出 \(B_i = i f(p_i - 1, i + 1, s - 1, n)\)。于是这题就做完了。
P7295 [USACO21JAN] Paint by Letters P
酷炫题
考虑问题是求连通块数,注意到图是一个平面图,于是我们可以用欧拉定理去求连通块数,即 \(|V|+|E|-|F|\)。\(|V|\) 和 \(|E|\) 都是好求的,我们考虑怎么求面数 \(|F|\)。
注意到,任意一个截断的矩形中存在的面都一定是原来的图形里就有的面,不可能裁剪后多出一个面,于是我们只需要找出原来的矩形中包含的面,这我们只需要对每一个字符 DFS 一边找出所有连通块即可。注意面是八联通。那么找出包含这个连通块的最小矩形,那么只要询问的矩形包含这个矩形则有贡献。
那么现在我们问题变成了有 \(O(nm)\) 个矩形,有 \(O(q)\) 个询问,询问一个矩形内包含多少矩形。这相当于一个四维偏序,考虑先排序 + CDQ 去掉两维,现在问题在于一个动态二维偏序,由于插入次数远大于询问次数,考虑二维分块,将复杂度平衡到插入 \(O(1)\) 询问 \(O(\sqrt{nm})\),于是总复杂度 \(O((nm + q \sqrt{nm}) \log {nm} + nm |\Sigma|)\)。
2023.12.23
今晚上要打 CF 了,感觉这几天状态不是很好,希望 CF 不会掉大分 😕
题单下面两道题面一样,一个最小化一个计数,害怕。
upd. CF 下分了哈哈
P7417 [USACO21FEB] Minimizing Edges P
最小化。
首先我们只关心每个点的最短路与奇偶性不同的最短路是多少,因为我们可以通过反复走一条边得到所有奇偶性相同的路径。我们记 \(a_i\) 为 \(i\) 的最短路长,\(b_i\) 为奇偶性不同的最短路长。注意如果是二分图则不存在 \(b_i\),此时答案就是 \(n - 1\)。
首先按照 \(a_i\) 分层,显然所有的边只能在同层或者在相邻层之间连。那么对于 \(a_i\) 来说,它的限制是每个点必须向至少一个上一层的点连边(除了第一层)。
对于 \(b_i\) 来说,有两种情况,一种是 \(b_i = a_i + 1\),这时候这个点是通过同层的边产生的,发现如果同层有边那么覆盖到的所有的点都满足 \(b_i = a_i + 1\)。对于其它的点,其连接的点肯定都与 \(b_i\) 差 \(1\),且至少有一个点等于 \(b_i - 1\)。
考虑贪心地一层一层连边。考虑到如果一个点的上一层存在 \(b_i - 1\),那么这个点肯定优先连这条边,因为它可以同时满足 \(b_i\) 与 \(a_i\) 的要求。否则,我们必须找到下一层中的一个 \(b_i - 1\) 的点与其连边。我们不妨先不确定与谁连边,我们只将每种 \(b_i\) 需要连的边的数量记录一下。对于后面一层的点来说,如果某个点 \(b_i\) 前面有一个需要连边的 \(b_i + 1\),那么它就会优先先向这个点连,如果没有需要连边的点了,再随便找一个点连边。但是这样可能会出现的问题是,有些点先向 \(b_i - 1\) 的点连边了,导致前面一些 \(b_i + 1\) 需要连边的点没有被连上,它们就得多连几条边,这显然是不优的。所以我们优先级应该是先连前面 \(b_i + 1\) 需要连的边,再往前连 \(b_i - 1\)。另外如果 \(b_i = a_i + 1\),那么这个点不可能向右面连 \(b_i - 1\) 的边,所以这种情况不记为有需要的边,直接自己与自己连,连点数除以二向上取整条边即可覆盖所有这样的点。
于是简单的写一个贪心即可。
好像正经做法是按照 \(a_i + b_i\) 为第一关键字 \(a_i\) 为第二关键字排序,那我这是编了个什么玩意(
实际上好像贪心是一样的,只是顺序有点区别,所以不管了。
P7418 [USACO21FEB] Counting Graphs P
计数题。
首先还是需要把二分图判掉,每个点随意往上一层连边即可。
考虑我们可以把连的边分为三种:
- \((a - 1, b - 1) \to (a, b)\);
- \((a + 1, b - 1) \to (a, b)\);
- \((a, a + 1) \to (a, a + 1)\)。
我们的限制是每个点的入度至少为 \(1\),同时每个点至少与 \(a-1\) 的点有一条连边。
如果我们把所有的 \((a, b)\) 全部画到二维坐标系上,那么所有的连边实际上只会与相邻的两个点相连。发现,每个点的限制只与三个方向的连边有关系,那么,我们按照 \(a_i + b_i\) 分层,依次考虑每一层的连边情况,即可考虑到所有的限制。容易发现每一层之间的连边是独立的,所以只需要将每一层答案乘起来即可。同样,每一层可能由若干连续段连起来,只需要把每一段的答案乘起来就行。
现在问题是:计算一段的答案。我们的问题大致长成了这样子:有一排点,每个点处有若干个点,现在需要将每个点向左连边或从上往下连边,要求每个点入度至少为 \(1\) 且两条边中至少连一条边(先不考虑 \((a, a+1)\) 的点),求方案数。
我们把过程分为两部分,先确定当前的点向左连的边,满足左边的点入度为 \(1\) 的限制,然后确定从上往下的连边情况,此时还剩下若干个点需要从右边往左连边,将这个状态传给下一个点继续做。那么根据这个可以设计两个 DP 状态 \(f_{i, x}\) 表示考虑到第 \(i\) 个点,第 \(i-1\) 个点有 \(x\) 个点需要连边,\(g_{i, x}\) 表示考虑到第 \(i\) 个点,此时已经有 \(x\) 个点与左边的点连了边。设 \(i\) 处有 \(p_i\) 个点,上面有 \(q_i\) 个点,则转移有:
其中 \(F(x, y, z)\) 表示一个大小为 \(x\) 的集合与一个大小为 \(z\) 的集合之间连边,满足 \(x\) 集合中前 \(y\) 个点与 \(z\) 集合中的所有点的度数至少为 \(1\),可以容斥计算:
然后还有 \(f(i, x)\) 的转移:
只有向左连边不向上连边的点才是成为需要连边的点,所以我们枚举需要连边的点,然后从向左连边的点里面选,剩下的点就都可以与上面任意连边了。
最后考虑一下 \((a, a+1)\) 的点,这些点可能会有自己与自己的连边,于是就枚举最后有多少点需要连边,然后在 \(p_i\) 个点之间任意连边,使得这几个点都可以被覆盖到。仍然可以容斥计算:
答案就是 \(\sum_{x=0}^{p_i} f(i, x) G(p_i, x)\)。如果最后一个点不是 \((a, a+1)\) 那答案直接就是 \(F(i, 0)\)。然后把所有的答案乘起来即可。
2023.12.25
旁观了 SoyTony 打 nfls simu。发现不会 T1。看了眼题解感觉非常深刻。
对于 \(a_1 \ge a_2 \ge \cdots\) 的数组,\((a_k, \sum_{i=1}^k (a_i - a_k))\) 是凸的,且斜率为 \(-k\) 切到的最小值点正好是第 \(k\) 个点。感觉很牛。
其实不太懂为什么 vscode 自带的 markdown 预览比 markdown preview enhanced 快很多,是不是 vscode 是增量更新,但是 markdown preview enhanced 每次整个重新渲染。导致博客长点就开始根本加载不出来。好像除了 vscode 自带预览不渲染 toc 之外区别不太大,所以决定现在还是用 vscode 自带的预览了。
也没准只是因为衡实机房因为一些奇怪的原因导致那个插件加载很慢,我不记得在本部的时候有明显的卡顿,摆了,
看到个题:区间加区间 \(\gcd\)。
P9331 [JOISC 2023 Day1] Passport
首先有个显然的 \(O(n^3)\) 的区间 DP,问题在于不太好转移。改一改定义,设 \(f_{i, j}\) 为当前可以到达 \([L_i, R_j]\) 的区间,这样转移就是从一段 \(f_{p, j}, f_{i, p}, f_{p, p}\) 转移来,线段树一下即可,\(O(n^2 \log n)\)。
好我们把这个扔掉。注意到我们实际在跑一个最短路,我们从 \([p, p]\) 开始,最后要到达 \([1, n]\),问题在于能不能把两个端点拆开。如果只要求到达 \(1\) 点,那么我们可以把这个问题直接变成一个最短路,即让 \(i\) 向 \([L_i, R_i]\) 的点连边,求 \(p\) 到 \(1\) 的最短路,这个只需要建反图,然后从 \(1\) 开始最短路即可,建图线段树优化一下。
但是我们并不能直接把两条路径加起来,因为有重叠部分。可以发现这重叠部分一定是从某一点开始到终点全部重合,于是我们可以从这个点开始再跑最短路更新答案。我们把所有的点的初始距离设为两条路径和然后再跑一遍最短路即可。
最短路可以换成 01-BFS,这样复杂度 \(O(n \log n)\),直接拿 dij 跑也行。
CF1119H Triple
手动 FWT 题。好像就是黎明前的巧克力的加强。
首先问题就是把若干个集合幂级数 \((x w^a_i + y w^b_i + z w^c_i)\) 乘起来,我们只需要求 FWT 后的乘积,然后再一边 IFWT 即可得到答案。
首先为了方便,先把所有 \(a_i\) 异或起来,这样就不考虑 \(a_i\) 了,不这么整也能做,就是更麻烦点。
然后考虑 FWT 之后长啥样,一个数的 FWT 系数一定是 \(1\) 或 \(-1\),那么 \((x + y w^b_i + z w^c_i)\) 的 FWT 实际上只可能是 \(x \pm y \pm z\) 四种情况,那么我们只需要知道这四种情况都有多少就能快速幂计算答案了。
这种题通常是把一些东西合起来跑一遍 FWT,然后再列方程求解。考虑设四种情况分别有 \(a_0, a_1, a_2, a_3\) 种。我们可以先把所有 \(w^b_i\) 加起来跑一遍 FWT,得到的值是 \(a_0 - a_1 + a_2 - a_3\),可以解出 \(a_0 + a_3\)。同理把所有 \(w^{c_i}\) 加起来跑可以解出 \(a_0 + a_1\),加上 \(a_0 + a_1 + a_2 + a_3\),此时只能凑出三个方程,还不足以解出答案。
考虑到 FWT 的系数应当是 \((-1)^{\mathrm{popcount}(i \mathop{\mathrm{and}} j)}\),我们考虑将两个系数乘起来,容易发现乘起来相当于把两个数异或后的系数,即 \((-1)^{\mathrm{popcount}(i \mathop{\mathrm{and}} j)} \times (-1)^{\mathrm{popcount}(i \mathop{\mathrm{and}} k)} = (-1)^{\mathrm{popcount}(i \mathop{\mathrm{and}} (j\mathop {\mathrm{xor}} k))}\),于是我们可以求 \(b_i \mathop{\mathrm{xor}} c_i\) 的 FWT,这时候的权值是 \(a_0 - a_1 - a_2 + a_3\),于是我们可以得到 \(a_0 + a_3\) 了。于是根据这三个信息就可以解出 \(a_0,a_1,a_2,a_3\) 了,于是就可以做了。
由此可以发现,当三个数的时候实际上我们可以用三个数的任意 \(2^3\) 种组合得到 \(2^3\) 个方程,同样也可以解出来,于是这个做法可以推广到任意多个数,只是组合数多了解方程可能会慢些。
CF1799G Count Voting
考虑一手容斥,发现不在自己组的限制最恶心,容斥掉,改成钦定若干在组内选,其它的任意选。先对每一个组内的选,记 \(f_{i, j}\) 表示选到 \(i\),还有 \(j\) 个未钦定,直接大力 \(O(n^3)\) DP 即可。由于最后的方案数是 \(\binom{n}{c_1, c_2, \cdots, c_n}\),那么 DP 算 \(\frac{1}{c_i!}\) 的乘积之和即可。然后再合并起来就完了。很简单。
CF1799H Tree Cutting
注意 \(k \le 6\),考虑状压。
定出根来,这样对每条边的操作要不然是把子树删去,要不然是只保留子树,删去子树则需要当前子树内还剩 \(a_{i - 1} - a_i\) 个点,保留子树则需要限制当前子树内还剩 \(a_i\) 个点。那么如果我们记录下子树内都进行了哪些操作,我们就能直接知道子树内还剩下多少点,进而可以判断当前能否进行这两种操作。而对于保留子树会更特殊一点,因为保留子树之后就不能进行其它子树的操作了,而保留子树必须在子树内的其它保留子树操作之前,于是我们单独记一维表示子树内最早的一个保留子树操作,这样就可以进行上述的限制了。
然后直接树形 DP 暴力合并即可。复杂度大致是 \(O(n 3^k k^2)\) 一类的,常数很小,可以通过。
2023.12.26
哈哈,我要放假,哈哈,哈哈!
水哥说回来把我文化课资料带来,我要学文化课了哈哈!
P6276 [USACO20OPEN] Exercise P
首先显然答案是环大小的 lcm。考虑直接枚举所有 \(p^k\),求有多少方案的 lcm 是 \(p^k\),这可以容斥一波,考虑 lcm 中 \(p\) 次数 \(\le k\) 与 \(<k\) 的方案数差一下就行,那么限制就是每个环的 \(p\) 的次数 \(\le k\)。
如果能快速计算答案就做完了。暴力 \(O(n^2)\) DP 即可 \(O(n^3)\),然后我不会了。
记 \(f(t)\) 为考虑 \(p^k\) 时的答案,那么大力 GF 一下:一个环的 EGF 是 \(A_t(z) = \sum_{i \ge 1} \frac{z^i (i-1)!}{i!} [i \bmod t \ne 0] = \ln \left(\frac{1}{1-z}\right) - \frac{1}{t} \ln\left(\frac{1}{1-z^t}\right)\),那么要求的答案就是 \(C_t(z) = \exp(A_t(z)) = \frac{(1-z^t)^{\frac{1}{t}}}{1-z}\),所求即 \([\frac{z^n}{n!}] C_t(z)\)。注意到这等于 \(n! \sum_{i=0}^n [z^i] (1-z^t)^{\frac 1t}\),而后面这个东西仅在 \(t\) 的倍数处有值,那么我们令 \(k = \lfloor\frac{n}{t}\rfloor\),后面这个东西就等于 \(\sum_{i=0}^k [x^i] (1-z)^{\frac{1}{k}}\),于是所求即为 \(n![x^k] (1-z)^{\frac{1}{k} - 1} = n!(-1)^k \binom{\frac{1}{k}-1}{k}=\frac{n!\prod_{i=1}^k(it-1)}{k!t^k}\)。看起来可以直接做了,但是注意这是在指数上的,所以需要模 \(P-1\),这是个合数,没法处理逆元。
而注意到这个式子除了 \(n!\) 以外只有 \(O(k) = O(\frac{n}{t})\) 项,这时候就扔出经典的 \(\sum_{p \in \mathrm{prime}, k \ge 1} \lfloor\frac{n}{p^k}\rfloor = O(n \log \log n)\) 了,于是这样的项数总和只有 \(O(n \log \log n)\),所以我们可以直接对每一项大力质因数分解,即可 \(O(n\pi(n) \log \log n) = O(\frac{n^2 \log \log n}{\log n})\),于是就可以通过。
CF1738G Anti-Increasing Addicts
大概想出来了个做法,但是由于做法是全感性胡的于是成功在构造处假掉。好耶。事实证明感性乱胡贪心确实很容易假,还是得证明证明。
定义偏序关系为一个点在另一个点的右下角,那么限制就是不存在长度为 \(k\) 的链,根据 Dilworth 定理,最长链等于最小反链覆盖,于是也就是说所有保留的点应该能划分成若干条反链覆盖,而在这上面的反链实际上就是仅往上或往右走的路径。于是实际上问题就是:能不能用小于 \(k\) 条路径覆盖所有的 0,且覆盖的点数为 \(n^2 - (n-k+1)^2\)。
感觉很抽象,先考虑一个没有限制的情况,那么我们感觉上实际上就是把右下角的一个 \((n-k+1)^2\) 的正方形扣掉,发现这时候恰好形成了 \(k-1\) 条路径,且这时候的路径总长是极长的。我们猜测,合法的路径方案一定是 \(k-1\) 条极长路径。简单画一画,发现极长路径肯定会贪心的把左下角和右上角的一个 \(k-1\) 三角形填满,否则一定小于 \(n^2 - (n-k+1)^2\),证明大概就是考虑第一条路径一定小于等于 \(2n-1\),第二条路径一定小于等于 \(2n-3\),以此类推,而每次必须取到上界才能到达 \(n^2 - (n-k+1)^2\),而卡到上界的方法一定是填满左下右上两个三角形的。于是我们可以看做是从 \((n - k + i, i) \to (i, n - k + i)\) 的 \(k-1\) 条路径,这样就不存在极长的限制了。
而现在问题是反链划分,我们考虑从右下到左上跑 DP,求到每个 0 的最长链的长度,那么最长链相等的点集一定是一条反链,于是让每条链覆盖这样的一个点集即可。注意我们不考虑三角内被覆盖的点,这些点一定会被覆盖到。构造方案则考虑贪心的去覆盖,采取能往上走就往上走的策略,让第 \(i\) 条链覆盖 \(k-i\) 的点集。由于最长链 \(k-i\) 的点集一定小于等于 \(n-k+i\),于是这些点一定是都可以覆盖到的,于是上述做法就是可行的。
P7154 [USACO20DEC] Sleeping Cows P
好蠢,我咋想不到这个。
首先肯定对两个数组排序。有个想法就是考虑什么时候一个点可以不被匹配,发现如果一个点不被匹配说明其对应的点一定都被匹配了,所以可以使用各种方法写出 \(O(n^3)\) DP。
这很差,因为你一直在考虑枚举某一边的信息然后快速维护另一边的信息,这导致你得多维护点东西。考虑把两个数组排序到一起,这样两边同时转移,这样就好多了。考虑 \(f_{i, j, 0/1}\) 表示考虑到 \(i\),有 \(j\) 个点需要向右匹配,前面是否存在点没有匹配,这样就能很轻松的 DP 了。
为啥我没想到把两个数组放一起排序然后 DP 捏,我怎么感觉我做过这种题的呢。蠢了。
2023.12.27
赛时 D2T2 连 SA 都没想是不是赛前一直在喝冰红茶导致的呢。
还是不要光说这种话了,感觉 thuwc 和 wc 要全考炸了,skill issues
to-do list 还有 11 题,能不能冲刺一下在月底前做完啊?感觉做不完。
thupc 决赛线 8 题。哈哈,明年继续捞 pku 的奖品去了。
P8276 [USACO22OPEN] Hoof and Brain P
图论,too hard。
这个是真的不太会了,我菜。感觉上应当是类似于“删一度点缩二度点叠合重边”类似的想法,不过是放在有向图上的。似乎有一些支配集的理解方式,不过感觉有些困难了,摆了。
首先容易发现如果一个点走若干步就死了那么肯定 Brain 胜。那么我们反向拓扑排序一边,把所有出度为 0 的点全部删掉。
那么现在得到了一个所有点度数至少为 1 的图。注意到,如果有一个点出度为 1,设这条边为 \(u \to v\),若最后两个点可以在 \(u\) 处相遇,那么这两个点一定可以在 \(v\) 处相遇,于是我们可以将这一条边缩起来。那么我们就可以大力缩边,最后得到一张出度至少为 2 的图。此时,如果两个初始点在同一个连通块内,肯定是 Brain 胜的,否则,两个初始点在新图的不同的两个点上,而度数至少为 2,那么显然一个点永远不可能被另一个点堵住,此时 Hoof 胜。具体维护方法就是直接 set 维护出边入边然后启发式合并就好了。
感觉比较容易想到这个的方法还是从那个经典方法去考虑?
P4217 [CTSC2010] 产品销售
模拟费用流。
但是一开始我让源点连 \(U_i/P_i\) 然后就很差。
考虑建模:
- \(S \to i: D_i / 0\)
- \(i \to T: U_i / P_i\)
- \(i \to i + 1: \infty / C_i\)
- \(i + 1 \to i: \infty / M_i\)
注意到 \(S\) 连出的边一定流满,而且显然连源点与汇点的边不会反悔,所以此时增广的顺序是不重要的,我们考虑从 \(1\) 到 \(n\) 依次增广。
要不然向左增广要不然向右增广,向右一定不会经过反悔边,所以可以简单用个堆维护出来最短的路径,向左可能会经过反悔边,所以需要拿线段树维护一下。我们拿两棵线段树来维护,一棵维护每条边被经过的次数,一棵维护每条边的边权,向左增广时我们先找到区间和的最小值,然后再找到区间内经过次数最少的边,这样我们可以得到一个最大能增广的流。注意到每增光一次会使左边一条路径被反悔完,于是这样增广的总次数是 \(O(n)\) 的。然后大力维护一下就行了,
CF1804F Approximate Diameter
有时候脑子真的很弱智,看到 tag 才意识到直接二分就完了,明明已经把该想的已经想到了。
首先我们盲猜一波任意一个点出发的最长的最短路是合法的。我们记从 \(u\) 出发的答案为 \(f_u\),那么显然真正的答案就是 \(\max f_u\),记为 \(d\)。显然有 \(f_u \le d\)。注意到,任意两个点之间的距离一定小于等于 \(2 f_u\),因为两个点一定可以在 \(u\) 处会合,那么也就是说 \(d \le 2 f_u\),即 \(\lceil\frac{d}{2}\rceil \le f_u \le d\),这是满足题目中的条件的。
那么加边怎么办呢?显然每次重新计算 \(f_u\) 是不现实的。注意到我们上述的条件是比题目给的条件的上界要紧的,所以考虑利用这一点。加一条边答案只会减少,而当答案减少一些的时候,注意到原来选的答案可能还是合法的,具体我们考虑新的答案为 \(d'\) 与 \(f'_u\),由于我们要求 \(f_u \le 2d'\),那么如果我们能保证 \(f_u \le 2f'_u\),则此时一定能满足 \(f_u \le 2d'\),而这意味这 \(f'_u \ge \frac{f_u}{2}\) 就行了。这意味着,只有当真正的 \(f_u\) 比原来的一半小后我们才需要更新答案,显然我们只需要更新 \(O(\log n)\) 次,那么我们每次二分找到这个边界即可,复杂度 \(O(n \log^2 n)\)。
2023.12.28
最终决定把年终总结咕了,因为真没啥可总结的,一年啥都没干,呃呃(
感觉不如板刷 2400* 的题了!
P7294 [USACO21JAN] Minimum Cost Paths P
应当说是很套路了。
考虑写个大力 DP,有:
由于第二维很大,我们就把它变成关于第二维的函数:
发现每转移一层做的操作实际上是,先加一个函数 \(x^2 - c_i x\),然后取前缀 \(\min\),然后再加上 \(c_i x\),显然这些函数都是下凸的,于是容易发现 \(f_i(x)\) 也是下凸的,那么就很好维护了,下凸函数前缀 \(\min\) 就是从极值点断开,后面一端变成一个常量,那么直接维护分段二次函数即可。
P8341 [AHOI2022] 回忆
贪心,过于恐怖。
这只能瞎写一通然后看能不能过大样例了(
这种类型的题很多了,AGC 应当是有若干道的,就是路径匹配问题,每次选择合并一些路径之类的。但是我每次碰到也都不会做啊。好困难。
本题的不同点在于:不同的限制可能会合并,也就是说可能当前节点两条链先不合并,再往上走走能够再满足一些限制,所以此时每次尽可能多合并是错误的。
首先发现如果两个限制是包含关系显然中间那个是不重要的。而如果有两个限制是交叉关系,我们可以猜测这样的限制一定会被某条链同时包含,于是可以将两个限制合并起来。但是这显然是有问题的,因为同一条链可能与多条链相交,而这多条链的起点可能不相同,无法一起合并。所以我们实际上还需要决策这样的链会与之前的哪条链合并。注意到只有一条链与之合并,而不与之合并的链肯定尽可能早与其它链合并更优,于是我们可以选取顶点最浅的那条路径,把这条路径与上面的路径去合并,剩下的路径则在对应的顶点位置加入路径集合。另外,如果没有路径与它相交,我们优先找一条与之不相交的路径延长到这里来覆盖它,如果无法找到这样的路径再新建一条路径。
于是我们将当前存在的链分成了两类:还没有满足限制的链与待匹配的链。没有满足限制的链在满足限制后加入待匹配的链的集合。
那么我们现在只需要处理经典的问题:将若干待匹配的直链合并起来,使得最后的链数最少。直接记录 \(f_u, g_u\) 表示当前点一共有多少直链,最少剩下多少直链,则 \([g_u, f_u]\) 内所有与之奇偶性相等的直链数都存在方案。合并两个子树时,我们让 \(g_u\) 更大的一边去合并到更小的一边,如果 \(g_u \le f_v\),那么说明这时候是可以让所有直链全部匹配的,于是新的 \(g_u\) 就是 \(f_u + f_v\) 的奇偶性,否则我们就让 \(g_u\) 与 \(f_v\) 匹配,剩下 \(g_u - f_v\) 条直链。
一些细节:注意到从一个点开始只有最浅的限制是有用的,所以对于每个点只用保留一个限制。在添加新的未满足限制的链的时候,如果 \(g_u \ne 0\),我们直接把这个孤立的链延长上来,否则如果 \(f_u \ne 0\),那么我们可以把某个合并的链拆开,将其中一条延长上来。
P6623 [省选联考 2020 A 卷] 树
直接套月球列车即可。
考虑求的是 \(\bigoplus_{v \in t_u} (val_v + dep_v - dep_u)\),无脑拍到序列上相当于 \(n\) 次询问求 \(\bigoplus_{v \in [l, r]} (a_v - x)\)。考虑拆位,对于某一位 \(2^k\) 来说,我们可以将 \(a_v\) 与 \(x\) 均对 \(2^{k+1}\) 取模,显然不会影响答案,然后发现对于某个 \(a_v\),\((a_v - x)\) 的 \(2^k\) 位是至多三段连续区间,于是我们可以对每一位直接跑二维数点就做完了,复杂度 \(O(n\log^2n)\)。BIT 的优越常数轻松跑过。
我们的先哲 lxl 曾经说过:这可以树上差分的啊,不要无脑拍成序列。我不知道她说没说过这个,我们钦定祂说过。所以你发现上述过程可以直接树上差分做,这样就 \(O(n \log n)\) 了。
P5290 [十二省联考 2019] 春节十二响
加这题的时候这题还是紫(
想了半天看错题了,然后又想了半天才会。我咋蓝题都得想这么久,彩笔。
考虑链咋做,相当于要将左右两条链上两两匹配,然后一个匹配的权值是两个点的最大值。容易发现每次将两条链上的最大值拿出来做匹配最优,证明大概交换一下就行了。
那么考虑一般的树上,我们直接合并子树,每次将两个子树当链来做就行了,拿堆维护一下,容易启发式合并做到 \(O(n \log^2 n)\)。
2023.12.29
accoders 有场模拟赛,感觉这逼题不如原神 OI。所以走了。
哦 T2 做法还是有点意思的,那给你升级一下吧,感觉不如 \(\lambda\)OI。
为什么我今年过了 200 道黑题啊?水题大师 apj。
闲话:\(k\) 个 \([0, 1]\) 内均匀随机变量 \(X_i\) 的最小值期望。
我趣我真的在 2024 前把这个 to-do list 做完了。很感动啊。
P8368 [LNOI2022] 串
这是真的好题!!!但是我想不到!!!
题目中所求的实际上可以看做每次在一个字符串后加两个字符,前面删一个字符,能进行的最多的次数。答案有一个显然的下界 \(\lfloor\frac n2\rfloor\),即从左到右依次拓展。
考虑把过程倒过来,也就是变成一开始选一个字符串,然后每次右边删两个字符左边加一个字符,那么考虑什么时候答案能比这个下界大,模拟样例即可发现肯定是删着删着这个字符串在 \(S\) 中出现了两次,于是我们可以跳到更靠右的一次出现,这样就能操作更多次了。注意到字符串长度逐渐减小,这意味着如果某一时刻一个字符串出现了两次,那么当再次走到这个串的位置时其一定仍然会出现两次,也就是说如果有一个串出现了两次那么我们就可以在这中间无限往回跳,不可能走到左边界,那么对操作次数的限制仅有右边界。记这样的字符串的第一次出现为 \([l, r]\),那么对于这个字符串来说最长的答案就是 \(r-l+1 + \lfloor\frac{n-r}{2}\rfloor\)。剩下的问题就是求出所有出现至少两次的字符串与第一次出现位置,这个容易拿 SAM 解决。
这么长时间没写 SAM 了我居然能一次写对 SAM,感动。
P9130 [USACO23FEB] Hungry Cow P
线段树分治基础练习题。
加入是简单的,只需要区间覆盖,直接线段树分治,然后在线段树上二分即可。需要正经写一下回溯操作,直接可持久化空间复杂度会炸。
AGC021E Ball Eat Chameleons
AGC too hard!!!!!
先枚枚举有多少红球多少蓝球,设红球 \(r\) 个,蓝球 \(b\) 个,可以简单分类讨论一下:
- 若 \(r < b\):显然无解;
- 若 \(r \ge b + n\):那么我们可以使得每个变色龙红球比蓝球至少多 \(1\) 个,那么任意方案都是合法的;
- 若 \(b \le r < b + n\):由于只要红球比蓝球多至少一个就一定是红色,那么我们肯定让恰好相等的尽可能少。容易发现可以通过一些调整,使得有若干变色龙红球比蓝球恰好多 \(1\) 个,其它变色龙蓝球与红球数量相等。
那么我们只需要考虑第三种情况。此时有 \(r - b\) 个变色龙差为 \(1\),\(n - (r - b)\) 个变色龙差为 \(0\)。注意到,对于差为 \(0\) 的变色龙,我们仅需要一次 RB 就可以使其满足条件,剩下的球可以随意分配给其它的变色龙。为了方便,我们将所有的球全部分配给差为 \(1\) 的变色龙。注意当 \(r=b\) 的时候,不存在差为 \(1\) 的变色龙,而注意到此时最后一个球一定是 B,所以可以变成求 \(r, b-1\) 时候的答案。
那么现在的问题就是:有多少 RB 序列,满足至少可以匹配出 \(n-(r-b)\) 个 RB 序列。这等价与最多有 \(b - (n - (r - b)) = r - n\) 个 B 是不能被 R 匹配的,这显然可以转化成格路计数,即从 \((0, 0)\) 走到 \((r, b)\) 不跨过 \(y = x + (r - n)\) 的方案数,可以得到答案为:
于是直接计算即可。
CF1592F1/2 Alice and Recoloring 1/2
其实不是特别难,不过我有点弱智。
首先发现两个版本操作二三都是唐氏,可以通过两次操作一代替。
那么实际上仅有操作一和操作四,对于 F1 来说,操作四的费用是 3,F2 的费用是 2。
操作是对矩形异或,那么先差分一下,现在相当于对四个点进行异或。操作一相当于每次可以翻转一个点,操作四相当于可以翻转 \((i - 1, j - 1), (n, j - 1), (i - 1, m), (n, m)\) 四个点。
对于 F1 来说,注意到任意两次操作四会翻转 6 个点,这时候操作一和操作四的费用是相同的,所以操作四最多只会进行一次,直接枚举进行的操作四即可。
对于 F2 来说,我们继续挖掘一些性质。注意到如果进行两次行相同或列相同的操作四,那么只会翻转四个点,于是这时候和操作一的贡献相同了,所以我们不会进行两次行或列相同的操作。发现这可以建出二分图匹配的模型,于是我们可以暴力跑个二分图最大权匹配啥的。但是右下角的操作与选几条边有关,于是我们要一条边一条边跑,显然跑不动。
注意到除了右下角以外,一次操作的贡献 \(\le 1\),显然贡献 \(\le 0\) 的我们不会选,那么我们只留下贡献为 \(1\),即差分数组三个点均为 \(1\) 的边,这样就不用费用流了,跑最大流即可。而每匹配一条边贡献加一,右下角的贡献仅会有 \(\pm 1\),所以这时候选的边越多越好,只需要跑一边最大流即可。
2023.12.30
下午放假,我要摆烂。