[整理]一些有趣的题目(包含大量近期 CF/AT 题)
CSP/NOIP 前发现自己智商严重不足,然后就来补了
正因智商不足有些题几乎是搬的题解
绝大多数是有一点思维含量的题,也可能会放一些我认为实现上细节较多或技巧比较常见的题
AtCoder 系列
ARC126E
\(n\) 个数,每次可以从一个数里拿出一个实数放到另一个并保证大小关系,获得这个实数的价值,每次修改一个数后求最大价值。
这题主要是发现一个神奇结论:最大价值就是所有数对的差之和的一半。因为显然我们要让操作时这个量减少最小,而每次操作大小相邻的数就可以达到这一点。
然后维护这个东西可以在权值线段树上维护值的个数、值的和、差之和,转移的式子推一下就有了。
ABC219G
一个无向图,初始权值为编号,每次选一个点把相邻点权都变成自己的,求最终局面。
发现有两种操作方式:暴力修改和打标记。由于它们分别对应了度数小和个数小,所以我们直接根号分治。
ABC218H
点亮一排灯中的 \(R\) 个,每个两边不同的位置都有一定贡献,求最大贡献。
妙妙妙题。
首先发现一定是点亮不相邻的灯,因为一定可以通过翻转一些灯使得点亮的个数不变而价值增加。如果 \(R>\lceil n/2\rceil\) 的话就反过来,是一样的。
然后就变成了某年的一道 JOI 题。
这个东西可以巧妙转化:因为每次要么添加一个要么翻转一段,而翻转一段带来的贡献就是两边的减去中间的。
ARC123D
给出序列 \(a\),构造两个序列 \(b,c\) 使得 \(b\) 不降 \(c\) 不升且 \(a_i=b_i+c_i\)。求两序列元素绝对值之和的最小值。
又是我想不出来的巧妙构造题!虽然题解也给出了斜率优化 dp 的做法
一个不降一个不升比较难受,先把 \(c\) 取相反数一下。
一般带有不降/不升的构造肯定是要往等号上靠的,然后就会猜到获得一个强大的结论:对于每个位置 \(i\),必然有 \(b_i=b_{i+1}\) 或 \(c_i=c_{i+1}\)。
为什么呢?因为我们发现,如果某个位置单调递增,那我们一定可以通过前缀加或后缀减的方式得到满足条件但更优的方案。
然后从前往后能不升就不升地构造即可。
还有一类构造需要递归地思考,例如 ARC125C。
ABC201F
给定一个排列,每次可以花 \(a_i\) 的代价将某个数移到任意位置或花 \(b_i\) 的代价将某个数移到开头或花 \(c_i\) 的代价将某个数移到结尾。求升序排列的最小代价。
这题的关键是知道每人最多进行一次操作然后进行分类:有一些人是不需要移动的,编号更小的需要移到开头,更大的移到结尾,剩下的只能直接插入。
dp 的时候需要使用数据结构维护最小值。
ABC199F
给定一个带点权无向图,每次随机选一条边把两端点权值平分,问 \(k\) 次操作后每个点的期望权值。
把这么简单的一个题放到这里主要是因为自己看到期望之类的就不敢下手做,其实这题的正解和期望关系不大。
看到很小的 \(n\) 和很多次操作可以知道它是一个矩阵优化,转移矩阵就是一次操作的期望变化。
然后随便分析一下每个点的权值从何而来就行了。
ABC195F
求在 \([A,B]\) 中选数(区间长度不超过 \(72\))使得任意两个数都互质的方案数。
这区间长度明摆着就是告诉你跟质数个数有关的状压,然后发现两个不互质的数一定是因为小于区间长度的数不互质的,然后就做完了。
ABC189F
\(0\) 到 \(n\) 的格子,每次可以随机向后跳 \(1\sim m\) 格,跳到有标记的格子会退回 \(0\),求跳到 \(n\) 的期望次数。
式子很简单,但是写出来后发现它会循环利用 \(f_0\),这时我们就把 \(f\) 写成关于 \(f_0\) 的方程最后解出来即可。
如果递推过程中需要用到未知的数,可以尝试解方程。
ARC119D
给定一个含有关键点的网格,每次可以选择一个关键点把所在行或所在列去掉,问最多能去掉多少个格子。
网格常见套路对于每行每列建一个点,把关键点对应的坐标连成一个二分图,然后删点。
对于删点我们肯定是尽量取造成影响最小的点也就是度数为 \(1\) 的点,这时对于图的情况分类讨论。
树可以直接删完,注意到最后一次删点横竖均可,所以森林的时候需要考虑每棵树最后删点的方向,显然全部横或全部竖。
对于其他情况,我们发现多余的边不会造成贡献,所以可以只处理生成树。
ARC115F
一棵带点权的树,初始有一些人,每个人有一个目标点,要求移动过程中每个人位置的点权之和最大值最小。
题面长得很二分,很可惜,最后并不需要二分。
给人的直觉就是一定要往点权更小的地方走,然而有目标点,那么把目标点扔进来一块跑就行了。
很神奇,这个直觉就是正确的。
ARC114E
一个网格纸上有两个黑格子,随机按网格线横竖切直到分开两个黑格子为止,求期望次数。
显然是要考虑这两个黑格子确定的矩形相关的,我们根据它对可以切的地方分成四周的和中间的,其中四周的必须在中间的之前切。
然后对于四周的每条线,它一定是所有比它更靠边的线和中间的线中最早切掉的,所以枚举每条线计算即可。
ARC112F
题面鬼畜,请直接去原题。
这诡异的替换很像进位,但和我们平时固定进制不同。为了切题迎难而上,我们强行把手牌和每个卡包看成一个第 \(i\) 位位值为 \(2^{i-1}(i-1)!\) 的数。
这样每一位替换就相当于进位,最后一位比较特殊,替换它相当于减去 \(N=2^nn!-1\),也就是 \(\bmod\) 这个数;抽卡相当于把手牌对应的数加上卡包对应的数。
那么现在问题转化成了找到关于 \(N\) 和每个卡包对应的数的不定方程的一组解,我们有两种做法:先枚举最终的数再构造序列或者 BFS 构造序列。
那这个东西就可以套路根号分治了。
Keyence 2021 E ARC111.5E
数轴上有 \(n\) 个隔开一个放的数,两个人轮流取数,A 随便取,B 选择一个两个数间的初始位置,每轮选择两侧更大的数走过去取掉。对于 B 的每个初始位置,求出 A 取的最大和。
很神奇的题,发现 A 每轮取很麻烦,所以直接强行让 A 歇着,等 B 走到想取的位置前再取。显然这个问题的最优解和原问题是等价的。
这样就可以方便地 dp 了,只需要记录被取掉的区间和 A 少取的轮数即可转移。
ARC110F
给出一个长度为 \(100\) 的排列,要求进行不超过 \(2\times10^5\) 次交换 \(p_i\) 和 \(p_{(i+p_i)\bmod n}\) 的操作将序列升序排序。
发现一串连续递增的子段可以通过依次操作一遍向前移动,那么我们只需要不断移动这个子段,把数一个个拼上去即可。
Codeforces 系列
CF1537F
给一张无向图,每个点有初始权值和目标权值,问能否通过对每条边两端点同时加减一个数使得权值达到目标权值。
先判掉需求和为奇数的。
观察性质,发现对于树我们可以直接做,否则可以把需求都并到一个环上。
还有一点是奇环上的点可以随便加偶数,根据前一步我们肯定可以把奇环解决掉。
对于偶环也就是一个二分图,两边的变化量是一样的,所以判断一下。
一些涉及到两个东西同时加减的问题,可能需要从奇偶性的角度考虑。
CF1536F
两人在一个 \(n\) 个格子的环形棋盘上博弈,每次可以在某个格子上写 \(\texttt{R}\) 或 \(\texttt{B}\),要求相邻格子不相同,无法操作者输。求两人都采取最优策略时的博弈过程数。
其实是诈骗,因为什么时候都是后手必胜,先手和后手的任意策略也都是最优策略。
然后就可以直接计算结束局面数乘上随便走的过程了,不过式子有点麻烦。
CF1556F
给一个完全图定向,每条边 \((i,j)\) 有 \(\dfrac{a_i}{a_i+a_j}\) 的概率指向 \(i\),求期望能到达所有点的点的个数。
套路地设一个 dp 状态 \(f_{i,S}\) 表示点 \(i\) 能到达点集 \(S\) 的概率,答案就是 \(\sum\limits_{i=1}^nf_{n,2^n-1}\)。
发现直接转移不了,这时需要用到一个常见的容斥 trick:\(f_{i,S}=1-\sum\limits_{T\subset S}f_{i,T}g_{T,S-T}\),其中 \(g_{T,S-T}\) 表示所有 \(T\) 和 \(S-T\) 之间的边都是 \(S-T\) 到 \(T\) 的。
然后这个 \(g\) 复杂度爆炸啊,不过没关系,我们预处理所有 \(g_{\{i\},S}\) 就可以 \(O(3^nn^2)\) 了,完全跑不满而且代码巨大好写。
CF1554E
懒得概括原题面了。
看到题面的 \(\gcd\) 后思维定势导致往 CF1559E 上想,结果失败了
考虑 \(\gcd\) 为 \(i\) 的倍数时的答案,最后容斥一下即可。
显然 \(i|n-1\) 时才可能有解,\(i=1\) 时答案为 \(2^{n-1}\),其他情况 DFS 构造一下发现最多为 \(1\)。
CF1540B
在一棵树上随机取一个点,之后每次随机从和取过的点相连的点中取,求取点序列期望逆序对数。
期望题咋总是有奇妙的搞法啊!!!
发现这个第一步很不确定,所以先枚举一个根,然后就是从上往下取。对于期望我们转化成枚举点对 \((a,b)\) 而更大的 \(a\) 比 \(b\) 先取到的概率加起来。
对于这样的点对,如果有祖孙关系那就已经确定了,否则就是从 LCA 往下走。发现这里很重要的是不管取了多少点概率是多少走向两点的概率是相等的,这样就可以直接 dp。
CF1534E
每次询问 \(k\) 个数的异或和,用不超过 \(500\) 次询问得到所有数的异或和或判断无解。
考虑每个数取到的次数,显然全都是奇数,并且它们的和是 \(k\) 的倍数,最大的数不能超过取的次数。
然后发现只要次数数组有了就可以构造出解。
CF1495E
猪三国杀,给出每人手里的无懈可击张数和所属阵营,求每个人出了多少张。
不妨设忠臣先出牌且忠臣总牌数更小,这样就是忠反忠反下去。
然后就可以一次记录忠臣出的所有牌并且传给下一个反贼,记录目前忠臣有多少牌没有被无懈掉,扫一遍即可。
CF1322C
懒得概括同上。
假设右部点连接的左部点集合没有相同的,然后就会发现一个傻逼的事实就是超过一个点的 \(\gcd\) 对答案没有任何影响。
CF1408E
毒瘤题意不概括了。
元素属于集合的一种转化是把元素和集合连边,然后发现一个显然而有用的事实是这个图中的环和原图中的彩虹环是等价的,所以我们直接对这个新图求最大生成树即可。
CF1491F
题面巨长不概括了。
巧妙的构造,首先可以尝试把每块和前面所有的计算,容易发现第一个非零位置就是第二块有磁性石。
然后我们发现第一块可以二分出来,后面每一块都可以直接比较出来,上界卡得死死的。
题外话:构造完了就会发现这题很多条件是没有用的,比如正负极(每次询问的两边至多有一块,所以不可能出现有磁性石但返回零的情况)、磁力强度限制(理由同上)等等,如果一开始考虑太多反而可能会带偏脚步。
CF1491G
进行不超过 \(n+1\) 次交换两枚硬币并翻转的操作,使所有硬币顺序排列并正面朝上。
怎么又构造啊?考虑对于每个置换环如何处理,发现如果只对当前环操作是不可能在规定次数内完成的,所以我们走歪门邪道,把两个环怼在一起,正好 \(n\) 次(别忘了出来的自环也可以用)。
还没完,如果一开始就只有一个怎么办?稍微手玩一下。
CF1408G
题意概括了就做完了,所以不概括。
观察题中条件,发现那个诡异的限制就是在说组内的边小于组间的边,这启发我们从小到大加边,每加出来一个团就可以把它分成一组。这东西好像是可以 dp 的,不过是指数复杂度,我们考虑还有什么性质可以利用。
从小到大加边,有点像我们做 Kruskal 的过程,而我们需要的 dp 状态考虑上连通性之后其实非常少,而 Kruskal 重构树正好可以供我们 dp,枚举子节点分了多少组即可。
CF1379F
给出一个 \(2n\times2m\) 的黑白交错棋盘,其中格子 \((1,1)\) 为白色。每次翻转一个白格,问能否在剩下的白格中放入 \(n\times m\) 个国王使得它们不互相攻击。
联系怪异的范围构造一下可以知道要切成一堆 \(2\times2\) 的块每块放一个,有些块只有一个位置能放。
那显然不能出现一个只能放右下的格子的右下方有只能放左上的格子,所以我们维护最左的左上和最右的右下就可以合并了。
CF1338D
给一棵树的每个点画一个任意平面图形,只有有边相连的点对应的图形要有交,求最长的完全包含链。
这个要求看起来很怪,但也很结论。其实手玩一下就可以发现这个东西的答案是任取一条链,链上每个点挂一层点的最大独立集,所以直接 dp 即可。
CF1446C
每个数向异或后最小的数连边,问至少删几个数能成为一棵树。
考虑树满足什么:除了恰好一个根,每个节点都有一个父亲,也就是恰有一对数是互相连边的。
然后删数不是很好考虑我们换成取最多,涉及到异或最小所以建 Trie,然后发现连边一定是连到兄弟子树中的。
所以如果有一边子树内部还能再连就不行,要扼杀掉,只留一个点。
CF1406E
从 \(1\sim n\) 的集合里猜一个数 \(x\),每次可以只询问 \(a\) 的倍数个数或询问 \(a\) 的倍数个数并删除(\(x\) 不会被删除),用不超过 \(10^4\) 次猜 \(n=10^5\)。
这个东西首先可以想到暴力猜质数幂,但显然过不了。于是我们自然想到常见的按质数大小根号分治,小质数暴力猜。
大质数麻烦一点,如果 \(x\) 有小的质因子,那么可以每个大质数问一次直接看它乘上了哪个大质数。否则需要删了再问过不了,那么对大质数分块,删完一块一起问就可以了。
CF1153F
给定 \(n\) 个端点在 \([0,l)\) 间均匀随机的区间,求期望被至少 \(k\) 段区间覆盖的区间长度。
我草这什么阴间题面?样例解释还有积分?弃了弃了
在Beta 函数闲谈中扯到了这题吊打 std 的做法,如果你比较暴力可以直接去那里。
结果其实是 dp,属实是被诈骗了。以下只考虑端点在 \([0,1)\) 内的情况。
发现算方案数可以转化成随机取一个点看是否合法,也就是在 \([0,1)\) 内随机取 \(2n+1\) 个点,有一个点合法的方案数。
这个可以直接 dp:设 \(f_{i,j,k}\) 表示前 \(i\) 个点、有 \(j\) 条线段未封口、是否取到了那个合法的点时的方案数,最终复杂度 \(O(n^2)\)。
CF468C
给定 \(a\in[1,10^{18}]\),求区间 \([l,r],l,r\le10^{200}\) 满足区间内数字的数位和是 \(a\) 的倍数。
由于 \(a\) 最大为 \(10^{18}\),而给一个长度为 \(10^{18}\) 的区间右移会导致数位和加一,所以我们就可以为所欲为,现在只需要求出 \([1,10^{18}]\) 的数位和即可。
这个东西显然是等于 \(45\times10^{17}\times18+1\) 的,所以直接算即可。
CF476D
构造 \(n\) 个所有数互不相同的四元组使得每组内两两 \(\gcd\) 都为 \(k\) 且最大数最小。
先扔掉 \(k\),然后考虑如何构造互质的。
因为一组最多有一个偶数,所以我们就放一个偶数三个奇数,容易发现 \(6k+1,6k+2,6k+3,6k+5\) 满足要求!所以我们就成功做掉了一个 MO 题
洛谷系列
P5361
题意比较杂乱不概括了。
首先转化一下变成 \((p+1)(q+1)>n\) 可以知道两个都尽量大就行。
但是两个问题看上去完全不搭边,而且后者还是个 NPC。
仔细一看发现前者我们是会做的:每次删掉度数最小的点,看什么时候最小度数最大。
那后者就只能近似算法乱搞了吗?联系第一问可以想到反正我想不到有一种近似算法是每次加度数最小的点然后删掉相连的点,容易发现求出第一问的答案后加入的点度数一定不能大于 \(p\),这时发现即使它是近似算法,求出来的 \(q\) 也能满足题目要求了。
P4370
对于所有 \(\dbinom ab\) 满足 \(0\le b\le a\le n\),选出 \(k\) 个使得和最大。
第一眼:这不是傻逼题吗?直接从下往上贪心取啊(一个傻逼的第一想法没错了)。
第二眼:哦我是傻逼不能直接取,不过也是一个堆能解决的事啊。
……草,取模之后怎么比大小啊??
偷看了题解草原来大数的比较还可以直接用对数啊。
P3454
给出一个格点多边形,求对称轴条数。
转化方式十分巧妙,因为对称轴两边的边和角一定都是对称的,所以直接跑 Manacher。
但是实现的时候会出问题:由于在角的值域内 \(\sin\) 和 \(\cos\) 都有对称轴,所以对于角度的哈希不能只使用点积或叉积,此处我直接两个一起判断就不会出问题了。
P2501
把序列 \(a\) 调整成单调递增的序列,求最小改变个数和最小改变量。
考虑最多能保留多少个数,发现两个数的差要不小于两数距离,移一下项可以发现需要求 \(b_i=a_i-i\) 的最长不降子序列,然后把剩下的 \(b_i\) 拉到合适的高度。
这个合适的高度通过调整法可以知道相邻 \(b_i\) 之间的一定拉到两端的高度。
具体实现的时候,枚举能转移到当前点的位置,对于中间的每个分界点计算代价。