2022 省选做题记录 3.0
3.16
「CF914F」Substrings in a String(bitset 优化字符串匹配,*3000)
开 \(|\sigma|\) 个 bitset \(t_i\) 存下每个字符在原串中的出现位置,修改也可以很好维护。
匹配的时候存一个 bitset \(ans\) 表示 \(y\) 在原串中的所有出现位置,初始全为 \(1\)。对于 \(y\) 的每一个字符 \(y_i\),将 \(t_{y_i}\) 左移 \(len-i\) 位再与上 \(ans\),即 \(ans\leftarrow ans\ \operatorname{bitand}\ (t_{y_i}<<(len-i))\)。求区间内的出现次数实际上就是数 \([l+len-1,r]\) 中有多少个 \(1\),这个可以通过右移分别得到 \([l+len-1,n]\) 和 \([r+1,n]\) 中的 \(1\) 的个数然后相减得到。
Code:https://pastebin.ubuntu.com/p/pm6JfDXvMB/。
「CF963D」Frequency of String(bitset 优化字符串匹配 + endpos 的性质,*2500)
引理:互不相同的长度之和为 \(M\) 的字符串的 \(\text{endpos}\) 集合大小之和不超过 \(n\sqrt m\)。
证明:互不相同的长度为 \(L\) 的字符串 \(\text{endpos}\) 集合大小之和为 \(n−L+1\),而 \(\sum L\le M\) 意味着最多只有 \(\sqrt m\) 种长度,得证。
用上一题的套路求出所有出现位置,然后用 _Find_first() 和 _Find_next(i) 扫一遍就行。
Code:https://pastebin.ubuntu.com/p/Wzt8G6RsMD/。
3.17
3.17 考试 T1 异灵树(结论题)
题面:
有一棵 \(n\) 个点的异灵树。他可以改变自身的根。
设在以 \(x\) 为根 \(y\) 子树内的点集为 \(T_x\left(y\right)\)。
\(q\) 次询问,每组询问给定 \(x, y\),求对于所有 \(u, v\),不同的 \(T_x\left(u\right) \cap T_y\left(v\right)\) 个数。
数据范围:\(1\le n\le 5\times10^4\)。
画图就可以发现,所有点的子树和 \(x\) 到 \(y\) 路径上割掉两条边的方案数就是答案,即 \(n + \binom{dist(x,y)}{2}\)。
CODE FESTIVAL 2017 Final J - Tree MST(点分治 + Kruskal)
一般地,对于(完全图)MST 问题,我们可以先选定一个 边集,做一次 MST(不连通不管),把剩余的边保留,最后再做一次 MST,这样一定能得到最优解。
这是一个树形结构,于是可以点分治,考虑跨过分治重心的路径。
以分治中心为根,令 \(p_u=w_u+dep_u\),则连接两个点的代价就是 \(p_u+p_v\)。
我们只需保留 \(p\) 最小的一个点,然后把其他点都和他相连,显然就是 MST 了。
这里会产生子树内自己连的路径,但是比直接连劣所以不会影响答案。
点分治一共会产生 \(\mathcal{O}(n\log n)\) 条边,然后跑一个 Kruskal 就 \(\mathcal{O}(n\log^2 n)\)。
Code:https://atcoder.jp/contests/cf17-final/submissions/30181981。
3.17 考试 T3 异离 / 「洛谷 P6199」[EER1]河童重工(点分治 + 虚树)
link:https://www.cnblogs.com/xsl19/p/luogu_P6199_sol.html。
3.17 考试 T2 随机字符串生成器(随机化 / 爬山)
题面:
在本题中所有英文字母均表示小写英文字母。
强强的 yzc2005 正在变魔术,魔术过程如下:
yzc2005 有一个随机字符串生成器,他首先选一位幸运观众为 \(26\) 个英文字母设定是元音(vowel)还是辅音(consonant),保证 \(26\) 个英文字母不全是元音也不全是辅音,并且由于幸运观众也不知道魔术师有何高论,所以元辅音状态是从 \(2^{26} − 2\) 种中等概率随机选取的。
然后随机字符串生成器按如下规则会生成一个长为 \(len\) 的字符串,其中 \(len\) 是一个提前设定好的数。每个字符都有一个权值,初始时全部为 \(1\),按顺序带权均匀随机生成每个字符,即生成 \(i\) 的概率是 \(\frac{v_i}{\sum v_j}\),每生成一个字符之后每个字符的权值将会改变:
- 如果生成了一个元音,每个辅音的权值变为 \(1\),每个元音的权值变为当前的 \(\frac{1}{2}\)。
- 如果生成了一个辅音,每个元音的权值变为 \(1\),每个辅音的权值变为当前的 \(\frac{2}{3}\)。
当字符串生成完之后,强强的 yzc2005 的妹子看到这个字符串,就能辨认出每个字符是元音还是辅音。
一旁的菜菜的 wasa855 看傻了,于是他找到了你,想让你做一个魔术揭秘,你需要对多个字符串分别判断每个字符是元音还是辅音。
正确率要求 \(99.5\%\) 左右。
数据范围:\(T=300\),\(len=3000\) / \(T=1000\),\(len=1000\)。
想法肯定是要找到 \(2^{26}-2\) 种中概率最大的一个,答案是概率最大的那个正确率最大。
由于概率可能很小,所以需要取 \(\log\) 后计算。这里有一个卡常技巧,可以先用 double 计算,等到值很小了再取 \(\log\)。
然后考虑随机调整,每次枚举每一个字符 flip 或整体 flip,但有可能陷入局部最大值,所以多次选取随机初始值进行调整,最后大概可以做到 \(99.5\%\) 的正确率。
Code:https://pastebin.ubuntu.com/p/BQQ9JNxtDm/。
3.18
3.18 考试 T1 包装 package(结论 + 贪心)
题面:
给定 \(n\),\(m\),求最小的非负整数可重集 \(S\),使得 \(\forall 1\le i\le m,i\in\Bbb{Z}\),存在 \(n\) 个可重集,每个的元素和都是 \(i\),且它们的并是 \(S\) 的子集。
数据范围:\(n\le 10^5\),\(m\le 10^{14}\) / \(n\le 10^6\),\(m\le10^{13}\)。
考试的时候以为是什么阴间结论题,结果还真是(x
直接搬题解了,因为懒得写(bushi

Code:https://pastebin.ubuntu.com/p/PdP3B8QyQP/。
3.18 T2 令人闻风丧胆的英文名称 bracket(DP)
题意:
给一个长度为 \(n\) 的括号串 \(S\),有 \(q\) 次询问,每次询问给定 \(l\) 和 \(r\),问有多少个 \(l\le x\le y\le r\) 满足 \(S[l\dots r]\) 去掉 \(S[x\dots y]\) 是一个合法括号串。空串也是合法的括号串。
数据范围:\(1\le n\le2500\),\(1\le q\le 4\times10^4\)。
考试的时候一直往前缀和和前缀 min 的方向去想了,导致 GG……
实际上这个 DP 很巧妙。
考虑预处理所有答案,设 \(f_{l,r}\) 为区间 \([l,r]\) 的方案数。
先预处理出来每个括号 \(i\) 匹配的位置 \(pp_i\),那么 \(f_{l,r}\) 可以从两个地方转移过来:
- 如果 \(s_l\) 为
(,\(s_r\) 为),那么将 \(l\)、\(r\) 相互匹配,方案数是 \(f_{l+1,r-1}\)。 - 考虑最终方案中一定会有 \(l\) 和 \(pp_l\) 匹配 或者 \(r\) 和 \(pp_r\) 匹配,枚举这两种情况然后容斥减掉都满足的一部分。
Code:https://pastebin.ubuntu.com/p/FZqxRqPDhV/。
3.19
3.19 考试 T1 灰色王子左特 zote(扩展欧拉定理)
题意:
给定 \(n\) 个数 \(a_1,a_2,\dots,a_n\),在每一对 \(a_i,a_{i+1}\) 中间添加一个加法或乘方符号,求所有 \(2^{n-1}\) 种方案求值的和。答案对 \(998244353\) 取模。注意加法优先级低于乘方,乘方定义为右结合的。
数据范围:\(1\le n\le 30000\)。
扩展欧拉定理:
由于当 \(\gcd\left(a,p\right)=1\) 的时候 \(a^{\varphi\left(p\right)}\equiv 1\pmod p\),所以上式可以等价于:
回到本题,考虑到在用扩展欧拉定理 \(30\) 次模数就会变成 \(1\),所以只要对长度不超过 \(30\) 的区间暴力计算贡献,之后不断扩展右端点贡献也是不变的。
所以我们只需要在快速幂的时候判断当前幂塔的值是否大于等于模数就行了。
Code:https://pastebin.ubuntu.com/p/hX2NZzqCr9/。
3.19 考试 T2 小 ds,确信 tinyds(排序 + 枚举,\(\mathcal{O}(n^2)\))
题意:
有 \(n\) 个物品,每个物品有 \(4\) 个属性 \(a_i,b_i,c_i,d_i\),你要把每个物品分配给两个人,使得:
- 所有物品都被选择;
- 每个人都选择了物品;
定义一种分配方案的价值为 第一个人的 \(\max\{a_i\}+\max\{b_i\}\) 和 第二个人的 \(\max\{c_i\}+\max\{d_i\}\) 之和,要求最小化价值。
输出最小的价值。
数据范围:\(1\le n\le 1000\)。
将所有物品先按照 \(a_i\) 从小到大排序,记录后缀 \(\max\{c\}\) 和后缀 \(\max\{d\}\),记为 \(pmxc_i\) 和 \(pmxd_i\)。
枚举第一个人选择的最大的 \(a_i\),将所有 \(i\) 之前的 \(b_j>b_i\) 的 \(j\) 全部拿出来再按照 \(b\) 从小到大排序,记录后缀 \(\max\{c\}\) 和后缀 \(\max\{d\}\),记为 \(smxc_i\) 和 \(smxd_i\)。
那么再枚举第一个人选择的最大的 \(b_j\),可以直接计算出这种情况下最小的价值。注意由于每个人都要选择物品,所以在算 \(\max\{c_i+d_i\}\) 的时候要和 \(\min\limits_{i=1}^n\{c_i+d_i\}\) 取 \(\max\)。
Code:https://pastebin.ubuntu.com/p/DMcCMmNMm6/。
\(\mathcal{O}(n\log n)\) 做法:

以及 \(\rm{\color{black}{w}\color{red}{yzwyz}}\) 神仙做法的 Code:https://pastebin.ubuntu.com/p/r8Vfn2fhGk/。
3.23
「JSOI2004」平衡点 / 吊打XXX(模拟退火)
模拟退火就是每次在一个范围内随机一个取值,如果它比当前解更优就更新当前最优解,否则以 \(e^{\frac{\Delta}{T}}\) 的概率接受当前位置,代码里的体现就是 if (exp(-Dlt / T) * RAND_MAX > rand()) tx = nx, ty = ny;(接受解)。
一些调参:随机种子:srand(19491001); srand(rand()); srand(rand()); 或者 srand(19260817); srand(rand()); srand(rand());;温度 \(T\) 初值 \(2000\),温度变化量 \(\Delta=0.9975\),eps 为 \(10^{-14}\),卡时 if ((double)clock() / CLOCKS_PER_SEC > 0.993) {printf("%lld\n", ans); exit(0);}。
代码:https://pastebin.ubuntu.com/p/7F9mt2dHNk/。
「NOIP2021」方差(模拟退火)
每次随机一个数操作退火 \(\to\) 可以有 \(40\) 分。
看出操作本质就是差分序列的置换 & 最优解一定是单谷的,分成两半排序后随机选两个数交换 \(\to\) 过大样例后 \(100\) 分。
就是这么离谱。
代码:https://pastebin.ubuntu.com/p/98rxcGSjMT/。
「CF1657E」Star MST(DP)
题意:
称一个无向完全图是 好的 当且仅当 其最小生成树边权和等于所有与 \(1\) 相连的边的边权和。
问有多少个 \(n\) 个点、边权在 \([1,k]\) 中的无向完全图是 好的。
数据范围:\(2\le n\le250\),\(1\le k\le250\)。
先找出所有点 \(u\) 与 \(1\) 相连的边权 \(a_u\),那么两个点 \(i,j\) 之间的边权就一定要 \(\ge\max{(a_i,a_j)}\)。
根据这个 DP。考虑依次确定 \(\{a_u\}\),设 \(f_{i,j}\) 表示考虑完所有 \(\le i\) 的边权,还有 \(j\) 个点的 \(a_u\) 没有确定且当前符合条件的方案数。
可以枚举 \(=i\) 的 \(a\) 有多少个,根据 \(\max=i\) 的边的条数转移。
代码:https://pastebin.ubuntu.com/p/5bN7YkxTBx/。
3.24
「THUPC2022 初赛」挑战(DP)
设 \(f_{i,0/1/2}\) 表示到了第 \(i\) 号格子,当前操作者 可以挑战 / 不能挑战 / 第一次操作不能挑战,第二次操作可以挑战 的最大胜率。
转移根据题意来即可。
预处理挑战胜率:根据挑战的参数 \(n\) 和 \(m\) 的大小关系计算得出,具体的,可以钦定选择的 \(u=i\) 然后列出式子。
Code:https://pastebin.ubuntu.com/p/BSskG2rxFS/。
3.25
3.25 考试 T1 鬼灵贼 spectral(DAG 的性质+ 特殊图的最大流)
题面:
给定一张 DAG。询问能否将边集划分成两个互不相交的集合,使从 \(A\) 出发经过某个集合能到所有点,从所有点出发经过另一个集合能到 \(B\)。
数据范围:\(1\le n,m\le10^6\)。
观察题目性质。一张 DAG 包含至少一个以 \(A\) 为根的外向树等价于除了 \(A\) 以外的所有点入度至少为 \(1\)。
内向树则等价于除了 \(B\) 以外的所有点出度至少为 \(1\)。
于是一条边可以满足一个入度条件或者一个出度条件。对于每个点拆出两个点 \(i\) 和 \(i+n\),建立最小割模型:
- 对于所有 \(i\not=B\),连边 \((S,i,1)\);对于所有 \(i\not=A\),连边 \((i+n,T,1)\)。
- 对于 DAG 上的一条边 \((u,v)\),连边 \((u,v+n,INF)\)。
- 那么对于一个点 \(i\),如果割掉的是 \((S,i,1)\) 的边,那么就表示这个点被满足到出度条件中,否则就被满足到入度条件中。
- 只有这张图满流(即最大流是 \(2(n-1)\)) 的时候才满足题目条件。
观察一下这张图的样子,可以发现:如果我们把所有连接 \(u\) 和 \(v+n\) 的边单独拿出来,那么对于一个连通块,它里面的点满流的充要条件是 这个连通块中的边数 \(\ge\) 点数。直接并查集做就行了。
Code:https://pastebin.ubuntu.com/p/X7hxFK3g32/。
3.25 考试 T3 肯德基 kfc(生成树 + 点分治)
题面:
KFC,全称 k-Factors Cactus(\(k\) 元仙人掌),即每个点最多在 \(k\) 个简单环中的图。
给定一个 \(n\) 个点 \(m\) 条边的 KFC,\(q\) 次询问两点间最短路。
数据范围:\(1\le n\le 10^5\),\(1\le m,q\le 2\times10^5\),\(k\le10\)。
看到这种多次询问图上两点之间的最短路的问题,大概率就是要拿出一棵生成树,然后在这棵树上进行树分治(其实与图上距离有关的东西就可以想到这个)。
这道题也是如此,把所有询问离线下来,在点分治的时候顺便传下去在当前分治重心控制范围内的询问。
考虑计算跨过分治重心的路径的贡献,把所有 不在生成树上 且 跨过分治重心的两个不同子树 的边拿出来,把这些边的端点打上标记,然后对有标记的点分别暴力跑一遍 BFS 求出它到所有当前范围内的点的最短路并且更新答案。递归子树的时候直接删掉这些边继续分治即可。

浙公网安备 33010602011771号