2023.03 做题记录
- CF1799G Count Voting【数数,容斥,dp】*2600
记 \(a_i\) 为第 \(i\) 个 team 的人数。
枚举出现 \(k\) 张作弊投给自己的票,贡献乘上 \((-1)^k\)。对于每个人,钦定有 \(b_i\) 张票来自队友,剩下的 \(c_i-d_i\) 张票随意。方案数为每个 team 将 \(a_i\) 张票分到 \(d\) 上的方案数乘起来,再乘上剩下的票的重排列方案数。
把组合数拆开然后两次 dp,复杂度 \(\mathcal O(n^3)\)。
- CF1799F Halve or Subtract 【结论,贪心】*2700
我们记 \(f(x)=\lceil\frac{x}{2}\rceil,g(x)=\max (0,x-b)\)。
假设 \(a_i\) 从大到小排好序了。
观察到 \(g(f(x))\le f(g(x))\),所以一定先除再减。
又观察到 \(f,g\) 都用的,一定是一个前缀(因为这样减掉的最多),因此先枚举这个前缀,这样剩下的操作用的也就是这个前缀后面的一个区间,这个区间也就固定下来了。
分析剩下的这个区间。如果一个数很大,我们肯定用 \(f\)。一个数很小,我们也会用 \(f\),中间段会用 \(g\)。所以最后的 \(a\) 序列应该被分成了五段:用 \(f,g\) - 用 \(f\) - 用 \(g\) - 用 \(f\) - 啥也不干。
前缀和 + two pointers。
- P7515 [省选联考 2020] 矩阵【差分约束,最短路】
首先可以轻松构造出一组特解,但是不一定满足值域限制。
因此目标就是调整值域。我们可以通过整行整列 \(+k\) 来做到。
记 \(r_i\) 为 \(i\) 行的调整值,\(c_j\) 为 \(j\) 列的调整值。发现这样是一个加法的限制,不会做!
但是观察到偶数行列取个反,就都变成减法了,也就可以差分约束了。所以就做完了。
- P6186 [NOI Online 2020] 冒泡排序 【数据结构】
观察冒泡排序和单点逆序对贡献的关系,每次做一个平移,然后全部 \(-1\)。
直接树状数组维护。
- ABC242Ex Random Painting 【容斥,期望,dp,数据结构】
进行 Min-Max 容斥。设 \(t_i\) 为覆盖到 \(i\) 的最早时间。
那么所求即为 \(E(\max t_i)=\sum\limits_{S\neq \emptyset}(-1)^{|S|+1}E(\min\limits_{i\in S} t_i)\)。
\(\min\) 是不是好做一百倍?设有 \(f(S)\) 个区间满足覆盖了 \(S\) 中的至少一个位置。那么 \(E(\min\limits_{i\in S} t_i)=\frac{m}{f(S)}\)。所以我们要干的事情就变成了,对于每个 \(i\),计算 \(f(S)=i\) 的 \((-1)^{|S|+1}\) 之和。这是可以 \(\mathcal O(n^3)\) 做到的。
把 \(dp_i(x)\) 看作一个序列,每次对其做操作。不难发现可以线段树维护。复杂度 \(\mathcal O(nm\log n)\)。
- P8292 [省选联考 2022] 卡牌 【容斥,数论,根号分治】
一眼寿司晚宴,那就根分,大于根号的质因子不超过 \(1\) 个。
可以先预处理出 \(f_{S,i}\) 表示钦定 \(S\) 中的质因子 (\(\le 43\)) ,是 \(i\) 的倍数的个数。
每次询问的时候,容斥,对于每一个质因子,强制出现或者可有可无,分别算一个 \(2^k\) 或者 \(2^{k}-1\) 乘起来。
- CF1750G Doping 【容斥,计数,生成函数】 *3300
首先钦定 \(k\) 个相邻,然后二项式反演。
枚举和原排列的 lcp,假设现在到 \(i\),前一半出现了 \(a\) 个相邻。枚举前一半,钦定 \(t_1\) 个相邻。枚举后一半,钦定 \(t_2\) 个相邻。那么前一半要在 \(a\) 个中选出 \(t_1\) 个,后一半在 \(n-i-1\) 个种选出 \(t_2\) 个,所以方案数为 \(\binom{a}{t_1}\binom{n-i-1}{t_2}(n-i-1-t_2)!\),这里 \(k=t_1+t_2\)。
暴力做,\(\mathcal O(n^4)\)。
观察到 lcp 后面第一位对于 \(a,b\) 的影响是 \(\mathcal O(1)\) 的,因此轻松做到 \(\mathcal O(n^3)\)。
考虑使用生成函数理解这个问题。我们有两个生成函数,分别是 \(F_{a}(x)=(1+x)^a\) 和 \(G_i(x)=g_j\times x^j\)。最后答案可以被表示为 \(\mathcal O(n)\) 个 \(F\times G\) 的系数和。
那怎么做呢。你以 \(1+x\) 为占位元化简,可以搞出关于 \(1+x\) 的多项式。直接秦九韶,复杂度 \(\mathcal O(n^2)\)。
- CF1804F Approximate Diameter 【估测,二分】*2700
要求是 \(0.5\sim 2\) 倍。考虑 \(1\) 到所有点的最短路的最大值,应该是标准答案的 \(0.5\sim 1\) 倍,所以输出这个值的两倍,也就是标准答案的 \(1\sim 2\) 倍是对的。
离线。我们观察到每次都算一遍实在太慢了,想想能不能一个答案多用几次。每次答案废掉的时候直径一定减少了一半,因此只会废除 \(\log n\) 次。每次二分出最远用到哪里,时间复杂度 \(\mathcal O(n\log^2 n)\)。
- CF1789F Serval and Brain Power 【根号分治,dp,暴力】 *2700
\(k\ge 5\) 的时候好做的,直接枚举分成 \(k\) 段,那么循环节一定在某一段中。
\(k\le 3\) 的时候也是好做的,分成几段 dp LCS 就行了。
\(k=4\) 不好做,但是被 \(k=2\) 包含了,所以做完了。
- P3688 [ZJOI 2017] 树状数组 【数据结构,概率】
发现求的是后缀和,因此问询的就是两个元素相等的概率。
树套树。
但是 \(l=1\) 的时候是错的,特判。
- P4548 [CTSC2006] 歌唱王国 【字符串,border,期望】
考虑一个生活中的赌场模型,将时间与金钱做联系。
可以参考题解区第一篇,以及我写的:link
- P3975 [TJOI2015] 弦论 【字符串,SAM】
SAM 板子,\(k\) 小子串。
首先建出 SAM 的 dag,计算一下每个节点后继个数。
\(k\) 小子串相当于 \(k\) 小路径。按位确定即可。
- P6640 [BJOI2020] 封印 【字符串,SAM,数据结构】
记 \(len_i\) 为 \(S\) 以 \(i\) 为结尾的前缀的后缀是 \(T\) 的子串的最长长度。建出 \(T\) 的 SAM 然后拿 \(S\) 上去跑一遍就行了。
问题变成区间查询 \(\max \{\min (len_i,i-l+1)\}\)。
\(i-len_i+1\) 单调不降,因此存在一个分界点,二分出来,两边分别查询。
- P4841 城市规划 【计数,生成函数,多项式】
套路:一般图方案数为 \(G(x)\),连通图方案数为 \(F(x)\),那么 \(e^{F(x)}=G(x)\)。所以 \(F(x)=\ln G(x)\),\(G(x)\) 是好求的,\(g_i=2^{\binom{i}{2}}\),做一下多项式 \(\ln\) 即可。
- P8290 [省选联考 2022] 填树 【计数,dp,拉格朗日插值】
我们假设计算值域为 \([l,r]\) 且 \(l\) 存在的答案,这相当于值域 \([l,r]\) 的答案减掉值域 \([l+1,r]\) 的答案。
区间长度是固定的 \(K\) 或者 \(K-1\)。在不断滑动的过程中只有 \(\mathcal O(n)\) 个关键点造成变化。因此对于每个区间,用树形 dp 任意算出 \(n+1\) 个值,然后拉格朗日插值。
- P3303 [SDOI2013] 淘金 【数位 dp,xor 粽子套路】
可以求出 \(f(x)=i\) 的个数,记为 \(c_i\),不为 \(0\) 的不多,可以数位 dp。
接下来我们要求的就是 \(c_i\times c_j\) 的前 \(k\) 大。\(k\) 不大,可以一个一个找出来。对于每个 \(c_i\) 维护当前到哪个 \(j\) 了,放入一个堆。每次取出堆顶,将对应的 \(i\) 的 \(j\) \(-1\) 再放回堆里。
- P7916 [CSP-S 2020] 交通规划 【对偶图,图论建模,区间 dp】
考虑 \(k=2\) 的做法。一定分成两个黑白连通块,那么相当于对偶图上的最短路。
\(k\) 更大也是一样的。首先相邻同色点缩起来,然后我们观察黑白点两两配对的顺序。不可能出现 \((1,3)(2,4)\) 这样的情况,因为换成 \((1,2)(3,4)\) 或者 \((1,4)(2,3)\) 更优。
这样相离或者包含的条件令人想到区间 dp。断环成链,记 \(f_{l,r}\) 为 \([l,r]\) 的最小代价。一种转移是 \(l,r\) 配对,还有一种是枚举一个分割点。
我们只要对所有的关键点算出最短路就可以转移了。时间复杂度 \(\mathcal O(Tn^2\log ^2n+Tk^3)\)。(是吗,反正能过就行.jpg)
很卡常,用 int,手写 pair,\(k=2\) 的时候最短路是对称的,跑一遍就好。
- CF1713E Cross Swapping 【并查集,2-SAT】 *2400
每个 \(a_{i,j}\) 是和 \(a_{j,i}\) 绑定的,所以为了使得字典序最小,我们按照顺序按位确定。
假设当前考虑到 \(a_{i,j}\) 和 \(a_{j,i} (i<j)\)。如果 \(a_{i,j}=a_{j,i}\),那么是否交换不影响答案。如果 \(a_{i,j}>a_{j,i}\),那么我们希望可以交换,也就是说 \(k=i\) 和 \(k=j\) 两个操作需要恰好做一个;如果 \(a_{i,j}<a_{j,i}\),那么我们希望不交换,也就是说 \(k=i\) 和 \(k=j\) 两个操作不能同时做也不能同时不做。
这个操作可以用带权并查集维护,时间复杂度 \(\mathcal O(n^2)\)。
- CF451E Devu and Flowers 【容斥,计数,生成函数】 *2300
这个题有很多的思考方式。
方法一:状压,容斥
考虑枚举出一个集合 \(S\),钦定其中的元素都是超过 \(f_i\) 的限制的。那么现在问题就变成了 \(s'=s-\sum (f_i+1)\) 个球分成 \(n\) 组,根据插板法方案数是 \(\binom{s'+n-1}{n-1}\),由于 \(n\) 很小,直接暴力算,复杂度 \(\mathcal O(2^nn)\)。
方法二:生成函数
对于每一种球建立 OGF,即 \(1+x+x^2+\dots x^{f_{i}}\),那么答案即为所有 OGF 的乘积的 \(s\) 次项系数。
但是 \(f\) 很大,不能暴力乘。考虑化为封闭形式,即 \(\frac{\prod (1-x^{f_{i}+1})}{(1-x)^n}\)。分母这部分可以再重新展开得到 \(\sum \limits_{i=0}^{\infty}\binom{n+i-1}{n-1}x^i\)。
枚举分子里面每一项取了 \(1\) 还是 \(-x^{f_{i}+1}\),这样分母对应的次数就确定了,也就可以得到所求的组合数。同上,由于 \(n\) 小,直接暴力算。复杂度 \(\mathcal O(2^nn)\)。
实际上不难发现两个方法推导出的最终结果是一致的。
- P6793 [SNOI2020] 字符串 【字符串,SAM,贪心】
对于两个子串 \(a_i,b_j\),修改的最小代价为 \(k-|\operatorname{lcp}(a_i,b_j)|\)。
所以我们要求出一组匹配的方案,使得 \(\sum |\operatorname{lcp}(a_i,b_j)|\) 尽可能大。
把两个串都翻转之后接在一起建立 SAM。把所有 \(A,B\) 的子串代表的节点标记出来。
我们在 SAM 的 parent 树上考虑这个问题:两两配对,代价为树上路径权值之和(\(\operatorname{LCA}\) 代表的就是 \(\operatorname{lcp}\))。这个问题显然可以直接在树上贪心。对于每个子树,尽可能内部匹配,不能匹配的传给父亲节点继续匹配。时间复杂度 \(\mathcal O(n)\)。
- P5308 [COCI2018-2019#4] Akvizna 【dp,斜率优化,wqs 二分】
不考虑 \(k\) 的限制做,最后由于是恰好 \(k\) 个再套一个 wqs 二分求回来。
如果不限制比赛轮数的话,有一个简单的 dp:\(f_i\) 表示剩下 \(i\) 个人最多赚多少。那么 \(f_{i}=\max\{f_j+\frac{i-j}{i}\}\)。
可以化成 \(y=kx+b\) 的形式,即 \(f_{i}=\max\{-\frac{1}{i}\times j +f_j+1\}\),直接斜率优化就行了。
- CF1808E Minibuses on Venus 【计数,容斥,dp,矩阵快速幂】 *2800
首先考虑 E1:我们计算 unlucky 的票数。假设总数位和为 \(s\),那么也就是不存在 \(a_i=j\),满足 \(2j\equiv s\pmod k\)。这东西很好做,直接 dp,枚举每一位选啥。复杂度是 \(\mathcal O(nk^2)\)。每一个 \(s\) 都要做一遍,所以复杂度是 \(\mathcal O(nk^3)\)。
对于 E2,\(n\) 变大了。考虑用矩阵优化这个 dp,可以做到 \(\mathcal O(k^4\log n)\)。但是这还不够。观察到每次乘的是一个 \(1\times k\) 的向量,所以单次乘法可以优化到 \(\mathcal O(k^2)\),整体复杂度就是 \(\mathcal O(k^3\log n)\) 了。
对于 E3,
这是什么?式子。推一下,不会。
- ABC293F Zero or One 【数据分治,暴力,二分】
一分钟胡的,不写了。
确定一个阈值 \(B\)。当进制 \(b\le B\) 时枚举所有的 \(B\) 并试除判断;当进制 \(b>B\) 时枚举 \(01\) 状态,二分出可能的 \(b\)。
复杂度 \(\mathcal O(T(B\log_{B}n+2^{\log _{B}n}\log n))\),应该取个 \(B=300\) 差不多。
- ABC295E Kth Number 【计数】
一分钟胡的,不写了。
首先转化成 \(K\) 大 \(\ge x\) 的方案数,假设分别为 \(b_1,b_2\dots b_m\),那么答案就是 \(\sum b_i\),相当于一个网格图你是竖着加起来或者横着加起来。
那就简单了,随便组合数算一下就行了吧。
- ABC292G Count Strictly Increasing Sequences 【计数,区间/数位 dp】
三十秒胡的,不写了。
考虑对于每一位有若干个分界点,分开之后区间内部就变成独立的了,那不是好做吗,设 \(f_{i,l,r}\) 表示第 \(i\) 位,搞到区间 \([l,r]\) 的方案数,然后分成更小的区间递归下去。
复杂度(应该)是四次方乘上一个 \(10\) 的常数(吧)。
- P3153 [CQOI2009]跳舞 【网络流】
二分答案,假设是 \(mid\)。
对于每个点,多拆出来两个点表示喜欢或者不喜欢。源点到男生连边,女生到汇点连边,流量为 \(mid\)。每个男生原点到对应的喜欢的点连 \(+\inf\) 的边,不喜欢的点连 \(k\) 的边,然后每个喜欢或者不喜欢的点到对应的女生连边。跑一个最大流,如果 \(=mid\times n\) 那么也就是满流,\(mid\) 可行,否则不可行。