各省省选做题记录
flag:NOI 前做完 2016-2023 的省选。要倒了,19 年都没做完。倒了,做 CF 去了,随缘更吧。
为啥省选打完了才开始做省选
不想写代码,那就不写了。
loj2433. 「ZJOI2018」线图
神秘人类智慧题。
考虑一下 \(k=2\),可以暴力建图。
考虑一下 \(k=3\),可以枚举共同的点,然后组合数算一下。
考虑一下 \(k=4\),发现对应到原图上要么是共一个点的三条边,要么是一条长度为 \(3\) 的链,也可以推式子。
这样就拿到了 \(30\) 分。
如果观察一下可以发现一个点只会涉及到图中不超过 \(k\) 的子图,这说明问题实际上可以被划分成一些独立的部分,那么可以枚举子图并且计算某个子图对应的点的个数。计数的方法可以暴力展开子图,然后减去子图的子图的答案。这样问题好像差不多,但是图的点数大大减小了。
那么考虑怎么计算一个子图对应的答案。发现可以暴力迭代 \(5\) 遍,然后套上面的做法。
那么只需要枚举所有子图,并且算这个子图在图中出现了多少次。求出现了多少次可以造个自动机暴力 DP。由于子图的个数不多,所以是可以通过的。
loj3115. 「SDOI2019」连续子序列
找规律题,我搞了一个 \(\mathcal{O}(T|s|^2\log k)\) 的做法,正解非常智慧。
结论:T.M. 序列可以和下述合并方式构成双射:每次把 \(01\) 合并成 \(0\),把 \(10\) 合并成 \(1\),如此做直到只剩下一个数。
所以对于 \(s\) 枚举所有可能的划分方式,暴力合并然后记搜即可,注意到合并方式是 \(\mathcal{O}(1)\) 种的。
loj3111. 「SDOI2019」染色
不会做!!!
暴力状态是 \(\mathcal{O}(nc^2)\) 的,如果尝试容斥等方法发现不行,所以只能优化 DP。
先压状态,考虑只记录有值的位置,这样状态就是 \(\mathcal{O}(nc)\) 了。拿线段树优化就是 \(\mathcal{O}(n\log c)\)。
大概是以复杂化转移的代价简化状态。
loj3113. 「SDOI2019」热闹的聚会与尴尬的聚会
想到了一个求出最大热闹度的算法:枚举答案,然后不断删掉度数小于答案的点。
考虑 \(k\) 正则图怎么构造 \(\dfrac{n}{k}\) 独立集,发现可以随便取点。上面的过程只需要每次删点的过程中决定是否加入独立集即可,可以类似证明。
开始想直接证明结论,反应了好久才想到那个求最大热闹度的算法。然后画了好多随机图,过了好久才想到讨论正则图。鉴定为菜。
不过这个题的结论还是相当有趣的。
loj3109. 「TJOI2019」甲苯先生的线段树
傻了,想了好久。
第一问是简单的,某个点到根的路径长度是 \(2x-\text{popcount}(x)\)。
考虑第二问,如何计数。先考虑一些指数暴力,考虑原式子:\(\text{dist}(a)+\text{dist}(b)-\text{dist}(\text{lca}(a,b))-\text{dist}\left(\dfrac{\text{lca}(a,b)}{2}\right)\),简单的想法是枚举 \(\text{lca}\) 然后算。观察到枚举 \(\text{lca}\) 之后,问题的形态就极其类似了,考虑针对此做一个刻画。于是可以发现每个点的权值都可以写成 \(k\text{lca}(x,y)+b\) 的形式,所以最后的的权值和就是关于 \(\text{lca}\) 的一次函数,可以拿这个解个方程。\(k\) 只和两边路径的长度有关,那么枚举两边长度,同时也可以发现 \(k>b\),因此枚举之后 \(\text{lca}\) 是可以唯一解出来的。
这样我们只需要算 \(b\) 为某个特定值的路径条数,而 \(b=\text{dist}(a)+\text{dist}(b)\),套用上面那个式子,枚举一下 \(\text{popcount}\) 之和,然后拿个 DP 算一下就好了。枚举长度 \(\mathcal{O}(d^2)\),枚举 \(\text{popcount}\) 用 \(\mathcal{O}(d)\),DP 用 \(\mathcal{O}(d^2)\),总复杂度 \(\mathcal{O}(d^5)\)。
loj3101. 「JSOI2019」精准预测
建立 2-SAT,然后判断两个点是否能同时生存相当于判定图上加两条边之后 2-SAT 会不会出问题。这个拿 bitset 算一下即可。
暴躁选手并不想卡常。
loj3096. 「SNOI2019」数论
整周期是好做的。
考虑剩下那部分怎么处理,相当于把 \(P,Q\) 都复制若干遍然后做点积,这是经典的 bitset 问题,容易做到 \(\mathcal{O}\left(\dfrac{PQ}{w}\right)\)。
上面那个东西优化没啥前途。考虑另一个暴力:选 \(a_i\) 中的一个数,然后复制 \(P\) 个,然后算这些数有多少个模 \(Q\) 之后是有数的。考虑优化这个过程,发现 \(a_i\) 游走的过程形如一个环,所以可以把环建出来做前缀和。复杂度 \(\mathcal{O}(P+Q)\)。
loj3093. 「BJOI2019」光线
无脑做法。
设 \(f_{i,j}\) 为 \(i\) 次反射之后打到 \(j\) 上的概率。可以用矩阵转移这个东西。
考虑答案,实际上就是:\(\sum f_{i,n}a_n\),或者说 \((\sum A^i)_{1,n}a_n\)。前面就是 \(\dfrac{1}{1-A}\),直接消元求逆是不行的,但是发现我们只要提取一项系数,且矩阵是带状的,于是直接消元复杂度为 \(\mathcal{O}(nd^2),d=3\)。
loj3094. 「BJOI2019」删数
憨憨做法。
考虑求单组,有一个直接的 DP 做法:设结果中最后一个非 \(0\) 的数为 \(i\),最小的调整值为 \(f_i\),有 \(f_i=\min f_j+\sum_{j<k<i}cnt_k+|cnt_i-(i-j)|\),拿线段树维护一下为 \(\mathcal{O}(n\log n)\)。
上面的做法显然没有前途,不过它给我们的启发是:问题实际上是选择一些关键点,关键点 \(a_i\) 的权值为 \(\max\{0,a_i-a_{i-1}-cnt_{a_i}\}\)。
考虑手玩观察以获取贪心结论。手玩得到的第一个事实是:我们不会把 \(cnt_x\) 的 \(0\) 选为关键点。考虑证明,即删去这个关键点之后,后一个关键点的贡献变化不超过它和前面关键点的间距。
上述证明提供了一个刻画问题的模型:假设选择 \(i\),则它可以免费覆盖 \([i-cnt_i+1,i]\) 的区间。考虑剩下没有覆盖的部分,可以发现覆盖一个只需要 \(1\) 的代价,所以答案就是未覆盖的部分的长度。
那我直接做个线段树覆盖就行了吧?不行,如果 \(i>n\) 那么不能拿它来覆盖。我比较直接,冲了个楼房重建。不过发现平移操作不会影响有效点,所以只要讨论单点修改即可。前者复杂度两个 \(\log\),后者一个。
loj3090. 「BJOI2019」勘破神机
相当于求:
\(m=2\) 的时候 \(f\) 是斐波那契数列,而这个东西是两个等比数列的和。\(m=3\) 的时候,可以写出递推式子:\(f_i=3f_{i-1}+2\sum\limits_{j<i-1}f_j\)。这也是一个整式递推式子,模仿上面的方法即可。
loj3091. 「BJOI2019」送别
大概拿 LCT 维护基环森林就好了(吧……)
loj3092「BJOI2019」排兵布阵
人傻了。暴力 DP \(\mathcal{O}(nm^2)\),然后瞎分析一通可以分析到 \(\mathcal{O}(nm\sqrt{m}+ms\sqrt{m})\),实际上直接分析就是 \(\mathcal{O}(nms)\) 的。
loj3089. 「BJOI2019」奥术神杖
挺好玩的。
首先把式子取个 \(\ln\),就变成 \(\dfrac{\sum \ln v_i}{c}\),容易想到 \(f_{i,j,k}\) 表示前 \(i\) 个 AC 自动机上到 \(j\),一共选了 \(k\) 个数。
考虑把并不是很重要的第三维去掉。发现答案形如 \(\ln\) 的平均数,可以想到 01 分数规划。
二元组 \((x,y)\),贡献为 \(x-ky\),很难不让人联想到 WQS 二分优化 DP,不过原理还是有差别的。
loj3087. 「GXOI / GZOI2019」旅行者
暴力可以做到 \(\mathcal{O}(nk\log k)\)。
注意到我们只需要求全局最小值,所以可以把多个源点塞在一起做,但是这样会丢失这些源点之间的信息。所以我们实际要做的事情是:构造全局的若干个划分 \((S_1,S_2)\),使得任意点对 \((u,v)\) 至少在一个划分中分属两个集合。有经典的 \(\mathcal{O}(\log k)\) 的划分方式。
一个单 \(\log\) 做法是:观察我们不能把所有源点塞在一起跑一遍的原因是:可能会回到自己。所以我们全塞进去跑一遍,然后求出某个点最近的特殊点,如果一条边两边最近的关键点不同,那么更新答案。首先这样的答案肯定比真实答案大,其次对于真实答案,其路径上必然有一个点连接两端关键点不同,所以这样一定能构造出答案。先构造再证明了属于是,这种思考顺序我也只在最优化见过。
loj3085. 「GXOI / GZOI2019」特技飞行
不会做/kk
手玩一下就可以发现操作最多是逆序对数量,也就是全部操作。
然后可以猜操作最少是置换环数量,严谨证明的话,可以不断调整?因为交换次数是不断减少的所以调整是收敛的(应该)
subtask2 是简单的,旋 45 度就好了。
没想出来可能是思维习惯的问题吧,我想题的时候更习惯于构建模型而不喜欢观察实际情况,以后要改变。
loj3056. 「HNOI2019」多边形
考虑能否用更直接本质的结构刻画问题,发现没有。
考虑能否 DP,尝试观察操作之间的阶段性,发现并没有什么阶段。
考虑手玩,发现最小操作次数实际上就是 \(n-1-\text{deg}_n\),显然这是下界,而且不难通过操作 \(1\) 构造出解。
所以达到最优解只需要每次都让 \(n\) 的度数增加 \(1\) 即可。考虑已经和 \(n\) 连接的边,它们实际上把多边形划分成若干个子问题,子问题之间是独立的。考虑在每个子问题进行操作,发现每个子问题的第一步是唯一的,且操作完之后,子问题又会划分成若干个子问题。也就是说,操作实际上构成了树的结构,我们只需要计数树的拓扑序。单组是容易的,多组考虑子树大小的变化量是 \(\mathcal{O}(1)\) 的,讨论一下不难维护。
loj3053. 「十二省联考 2019」希望
大概想到了做法。
考虑 \(|V|-|E|\) 容斥,转化成求 \(f_i\) 表示包含 \(i\) 的且距离 \(i\) 不超过 \(L\) 的连通块数量。
考虑放一起做,设 \(f_{i,j}\) 表示距离 \(i\) 距离不超过 \(j\) 的连通块数量,这是一个类似换根的过程。利用链分治来模拟这个换根的过程即可。细节比较多。
维护的过程中有几个有用的 tips,可以参考:
- 前缀乘和后缀乘等价(拆成全局乘和前缀乘)
- 可以利用主席树来维护 \(f\) 的版本,也可以利用可回退的数据结构,每次在链上回退来得到每个版本。
loj3047. 「ZJOI2019」浙江省选
中途编了个假做法然后直接看题解了,有点可惜。
考虑 \(m=1\),就是求凸包。
考虑 \(m=2\),观察什么样的点可能成为第二,首先它一定位于其余点的上凸壳上面,其次,剩余直线覆盖它的优势区间的次数不超过 \(2\) 次。那么可以二分某个直线与凸壳的交点(具体地,判断是否在左侧交点左侧只需要满足当前直线的斜率大于二分直线的斜率,且两直线交点在二分直线的优势区间右侧),并对这个区间执行整体 \(+1\)。最后只需要判断一个直线的优势区间是否有区域只被覆盖一次即可。
扩展到 \(m\) 为任意同理,复杂度为 \(\mathcal{O}(nm)\)。
在凸壳上做操作还是要比一般的直线集合方便的。
loj3046. 「ZJOI2019」语言
编了个垃圾做法,先树剖然后套链上的做法即可,复杂度三个 \(\log\),换成 GBT 两个。
不过考虑上面的思路,即维护经过每个结点为根的路径覆盖的位置,设 \(f_{u,i}\) 表示 \(u\) 覆盖 \(i\) 的次数,\(f\) 数组可以通过线段树合并得到,而且对于每条路径的修改是 \(\mathcal{O}(1)\) 的,所以可以单 \(\log\)。
感觉比较神奇,不如写常规做法。
loj3045. 「ZJOI2019」开关
不会生成函数。
考虑求 \(f_i\) 表示 \(i\) 次恰好完成的概率。先求出到达状态的概率,再容斥掉之前已经到达状态的概率。利用生成函数刻画:
解决这类问题需要式子的形式,还需要弄明白所求。我们要求 \(\sum if_i\),即 \(F'(1)\),也即 \(\dfrac{H'(1)G(1)+H(1)G'(1)}{G^2(1)}\)
不过这样并不好直接带入式子。考虑将式子展开。首先 \(H_e(x)=\sum a_ie^{ix/\text{sum}}\),有 \(h_i=\sum_w a_w(w/\text{sum})^i\),那么 \(H_o(x)=\sum_i \sum_w a_w(wx/\text{sum})^i=\sum_w\dfrac{a_w}{1-wx/\text{sum}}\),\(G_o(x)\) 类似。
求完之后直接带入即可,不过发现 \(x=1\) 处并不收敛,所以可以上下同时乘 \((x-1)\) 解决这个问题。带入式子是平凡的。
还有一种做法是观察到期望转移式子是异或卷积的形式,然后根据 FWT 推个式子,因为比较懒所以就不写了。
loj3044. 「ZJOI2019」Minimax 搜索
先编一个复杂度爆炸的做法,枚举代价,然后求出每个点可行的值域区间,这样得到了一个判断算法。套一个枚举就 \(\mathcal{O}(n2^n)\) 了。
考虑计数,先枚举权值容易想到设 \(f_{u,l,r}\) 表示 \(u\) 的值域区间为 \([l,r]\) 的选择集合的数量。这样是三方的。然后发现个事情,就是原先的答案一定被包含在值域区间里面,而且限制只需要满足区间大小超过 \(1\) 即可,所以我们只关注左右端点和原先答案的大小关系,这样状态就是常数级别的。写个线段树合并或者动态 DP 之类的东西就好了。
loj3043. 「ZJOI2019」线段树
和 [ZJOI2020]传统艺能 基本一样,拿个线段树每次更新五类点即可。由于涉及到一些奇怪操作(比如在叶子处 pushup)忘记初始化 WA 了一发。
loj3042. 「ZJOI2019」麻将
离谱。
以时间为阶段 DP,显然不可取,考虑通过 DP 构造加入 \(i\) 张牌之后的不能胡牌的状态。发现判断是否胡牌并不是一个平凡的问题,稍作思考可以得到如下 DP:\(f_{i,x,y}\) 表示考虑 \(i\) 张牌之后,\([i-1,i]\) 的连续段有 \(x\) 个,\([i]\) 的连续段有 \(y\) 个的最大面子数量,不难处理转移。不过考虑 DP of DP 的话,状态数似乎有些多。
点开题解,发现状态数并不多,冲个 bfs 就过了。不过我的状态有 \(6419\) 个,不知道为什么。
loj3328. 「SNOI2020」水池
挂三个标记即可,不要像我一样把维护权值和维护标记的结构体分开,否则会忘记下传很多标记(不过估计除了我没人会这么写)
loj3327. 「SNOI2020」排列
bot 题,只会照搬 zx2003 的做法。
先观察一下问题的整体形态,帮助我们理解问题,可以发现一些事实:
- 对于没有出现的极大连续段,它们一定出现在一起。
- 假设最后一个数为 \(p_k\),则 \(p_k\) 左侧值域连续段递减,\(p_k\) 右侧值域连续段递增。
- 考虑既包含已经确定的段又包含还未确定的段的连续段,已经确定的部分一定构成连续区间,并且填的过程中会优先把中间填满。
上述性质都可以通过调整等方法证明。至此,最优解的形态已经露出部分轮廓,如果使用贪心并依照上面的原则构造最优解,顶多把 \(n\leq 20\) 骗过去。因此我们考虑构建 DP 模型。
DP 的决策主要体现在,如果当前出现了新的区间,则对于当前区间左右侧的极长连续段,我们应该先添加左边还是先添加右边,同时我们还需要计算贡献。我们在左右连续段上统计贡献,考虑贡献为连续段内所有数的条件,发现假设在到达当前值域区间的过程中,如果它被中间用来填坑的元素覆盖了,那么它的贡献就为 \(1\),否则贡献为连续段长度。可以想到建立 DP 数组 \(f_{i,s_1,s_2}\) 表示到达 \(i\) 之后左 / 右连续段填了 / 填了且被覆盖 / 填了且没有被覆盖。
但是因为这道题是 bot 题,所以还需要亿些些分类讨论,包括 合法状态 / 合法转移 / 贡献分布 各方面,在此略去。
对于我而言最有意义的就是对模型形态的整体观察,虽然我们并没有推出较为具体的结论,但是却更深入地理解了模型,使我们更加靠近正解。bot 思维,学不会。
loj3324. 「SNOI2020」取石子
打表发现对于固定的 \(n\),可行的 \(k\) 是一个后缀,假设 \(f_n\) 为后缀的开头,可以发现 \(f_{Fib_i+1}=Fib_i\),进一步观察发现 \(f\) 数组是按照 Fib 方法复制得到的(即前 \(Fib_n\) 个数是前 \(Fib_{n-1}\) 和 \(Fib_{n-2}\) 个数拼起来的),容易计算。
尝试证明。首先转化问题,取到倒数第 \(2\) 个石子的人获胜。根据经典结论,先手的第一步方案应该是取掉 \(n\) 的齐肯多夫表示法的最低位,那么大胆猜想先手必败的 \(k\) 的最大值就是让 \(k\) 不能取到最低位,事实也确实如此。证明和原问题是相同的。
loj3315. 「ZJOI2020」抽卡
不会生成函数,写一个基于 min-max 容斥的平方做法。
先考虑一个怎么求,那么我们先考虑嵌套的部分的容斥系数,容易得到式子:\(f_i=\sum_{i-j<k}f_j\)。不过打个表其实可以发现 \(f_{tk}=-1,f_{tk+1}=1\)。再考虑把这些段划分成若干整段,设 \(g_{i,j}\) 表示长度为 \(i\) 覆盖了 \(j\) 个点的容斥系数和,那么 \(f_xg_{i,j}\to g_{i+x,j+x}\),但是 \(f_x\) 有优秀的性质,所以考虑一个类似完全背包的过程:每次塞一个长度为 \(k,k+1\) 的段,并考虑是否和前面的段合并,这样可以囊括所有情况。
loj3501. 「联合省选 2021 A | B」图函数
感觉出得很好。
题目限制比较多,先理解一下题意。\(f(u,G)\) 表示从小到大考虑每个点 \(v\),若 \(u,v\) 强连通则把 \(v\) 删去,计数器自增。\(h(G)=\sum f(u,G)\)。事实上可以发现如果把遍历到的时候不强连通的点 \(v\) 删去的话对强连通性并不影响,所以假设 \(g(u,v,G)\) 表示 \(u,v\) 路径上编号最小的点,则有 \(f(u,G)=\sum_v[g(u,v,G)=v]\),同时有 \(h(G)=\sum_{u,v}[g(u,v,G)=v]\)。
此时题意已经被简化到了可以被理解的层面,着手设计算法。观察 \([g(u,v,G_i)=v]\) 产生贡献的为 \(i\) 的一个前缀,考虑求出 \(v\to u\) 和 \(u\to v\) 只经过 \(\geq v\) 的结点的瓶颈路,利用 Dijkstra 算法可以得到一个 \(\mathcal{O}(nm\log n)\) 的算法,利用 Floyd 算法可以得到一个 \(\mathcal{O}(n^3)\) 的做法,由于本题图比较稠密所以理论上 Floyd 更优,卡常可以通过。
考虑另外一个思路:从大到小加边。一个暴力的想法是,枚举 \(v\),然后在图上只保留 \(\geq v\) 的点,并同时维护联通性。这样子显然是不优秀的,因为我们需要对每个 \(v\) 都进行计算,产生了大量冗余的过程,考虑将它们合并处理。暴力的合并思路是,维护满足联通且路径编号 \(\geq i\) 限制的数组 \(t_{i,j}\),每次加入一条边 \((u,v)\) 的时候,枚举满足 \(t_{i,u}=1\) 的点并从 \(u\) 开始暴力 dfs 所有点,这样复杂度可能达到 \(\mathcal{O}(n^2m)\)。但是发现这个过程是可以剪枝优化的,因为我们并不需要重复搜索 \(t_{i,u}=1\) 的点,如此,由于对于一个 \(i\),\(t_{i,*}\) 最多变化 \(n\) 次,可以得到复杂度上界 \(\mathcal{O}(n(n+m))\)。
看似已经足够优秀,但是本题还是可以优化,仔细观察过程发现我们进行了如下冗余运算:
- 枚举边的时候会枚举到无用的结点 \(i\)。
- dfs 时可能存在出边不能被遍历。
利用 bitset,找到 bitset 中所有 \(1\) 即可规避不合法点,复杂度 \(\mathcal{O}(n^3/\omega)\)。
我在处理本题的时候,没有仔细理解题意便尝试着手设计算法,从而没有把握好问题的层次,走了很多弯路,本题的多种思路也让我失去了对思考顺序的把握,以后要注意。
loj3956. 「联合省选 2023」城市建造
建立圆方树可以发现图和树几乎是等价的,下文只讨论树。
存在一个 DP 做法:枚举连通块的较小的一个大小 \(d\),则若割掉与某点相连的边,会得到一个新的子问题,否则连接的子树内不会有割边。可以设 \(f_u\) 表示 \(u\) 子树的答案,且 \(u\) 子树,每次考虑一条边是否应该割掉,可以得到一个 \(\mathcal{O}(n^3)\) 的做法。
发现我们并没有很好用到 \(k\) 的性质,考虑退而求其次,考虑 \(k=0\) 的做法。观察上述 DP 做法可以发现:若子树大小 \(\geq d\) 则它子树内必定有被割掉的边,那么当前边也应该被割掉,否则若子树大小 \(<d\),它不应该被割掉,所以可以得到一个性质:
\(k=0\) 时,若连通块大小固定,方案唯一。
容易得到 \(\mathcal{O}(nd(n))\) 的做法。
将其扩展到 \(k=1\) 的情况,发现割边的限制仅仅变成了 \(>d\) 和 \(<d\) 的决策确定,而 \(=d\) 的决策仍然是很少的,枚举大小可以得到平方做法。
不过实现后其实可以发现合法的联通块大小是很少的,考虑证明。发现假设连通块数量为 \(c\),由于 \(k=1\),所以只能是 \(\left\lfloor\dfrac{n}{c}\right\rfloor,\left\lceil\dfrac{n}{c}\right\rceil\),而这个级别是根号的。需要剪枝。
上述推导已经提示我们合法的大小不是很多,进一步观察上述过程可以发现:
若把子树大小排序后做前缀和,则合法的大小一定是前缀和或者前缀和 \(+1\)。
所以对于一个点,合法连通块大小是 \(\mathcal{O}(deg_u)\) 级别的,所以总状态数不超过 \(\mathcal{O}(n)\)。
所以只要考虑转移即可,事实上,如果从大到小暴力考虑每个子节点,并加入 DP 状态,便可以在不超过子节点总状态数之和的时间内求出所有状态,总复杂度线性。
为了避免一些不必要的讨论,可以把重心拉到根,这样根一定在被删的点之中。
本题通过观察一个暴力 DP 过程可以得到不少的成果,不过证明合法连通块个数大小为根号是需要一些技巧的。标算的状态数和转移数分析非常 educational。
loj3957. 「联合省选 2023」人员调度
可以发现是个费用流模型,然后发现可以模拟流,然后套个线段树分治就做完了,三只 \(\log\)。
撤回有点麻烦,可以多开几个存撤销信息的栈,比如线段树操作,赋值操作等。
P8367 [LNOI2022] 盒
Solution
可以推出来一个这个式子:
大于的部分是对称的。
直接化简是不可行的(虽然可以推但是不会,咕咕),考虑递推。令 \(f(x,y)=\sum\limits_{j=0}^{y}\dbinom{j+x-1}{x-1}\dbinom{S-j+n-x-1}{n-x-1}\),在 \(y\) 上 walk 是简单的,但是在 \(x\) 上 walk 做不了。
考虑寻找原式子的等价形式,上面已经提到了难以化简,考虑组合意义,可以想到将组合数和格路计数建立联系。则相当于从 \((0,1)\) 走到 \((j,x)\),再从 \((j,x)\) 走到 \((S,n-1)\) 的方案数,需要保证走到第 \(x-1\) 行的时候不超过 \(y\)。由于路径是递增的,考虑一个等价表述:超过 \(y\) 的部分在 \(x-1\) 后,则可以得到:\(f(x,y)=\sum\limits_{j=x+1}^n\dbinom{j+y-1}{j-1}\dbinom{n-j+S-k-1}{n-y}\),发现这个式子可以在 \(x\) 上 walk,所以我们实现了 \(\mathcal{O}(1)\) 在参数 walk。由于坐标是递增的所以复杂度为 \(\mathcal{O}(n+S)\)。剩下的问题是对称的。
Conclusion
涉及到的组合数问题的处理技巧:
- 暴力化简 / 组合意义(这题用到了格路计数)
- 递推,这题的递推从式子的两个等价形式出发得到了在不同维度上的递推方式,很巧妙。
P8368 [LNOI2022] 串
Analysis
瞪了一下会一个点数 \(\mathcal{O}(n^2)\) 的 DAG 上最长路,又瞪了一下发现会了一个点数 \(\mathcal{O}(n)\) 的最长路,但是不会处理。
观察一下,发现有一个 \(\dfrac{n}{2}\) 的构造,然后过程相当于在串上来回跳。然后就没看出来什么东西。
Solution
观察可以一个串如果出现了至少两次,那么它一定能被经过。构造不难。
那么一个串能被经过的充要条件就是它出现了两次或者它前面一个出现两次的串能递推到它。利用 SA 可以解决问题
Conclusion
没什么好说的,观察还是比较吃直觉和灵感。
记得看一下 ix35 做法。
P8293 [省选联考 2022] 序列变换
Analysis
开始建了个括号树,没啥头绪,后来画了个根往下连三条链的树,然后发现如果我们把这层点连到下一层点上面,那么就不急着动这些点,因为可能后面的操作会给这些点带来新的兄弟,于是每次都需要把根删到只剩一个儿子,然后往下做。继续观察,发现每层处理的点恰好为这个深度的点。
考虑 \(x=0,y=1\),直觉是每次删掉最大的,贡献是 \(sum-\max a_i\)。
考虑 \(x=1,y=1\),仍然是删掉最大的,贡献是 \(sum+(sz-2)mn\)。
考虑 \(x=1,y=0\),如果还是考虑删掉最大的就错了。观察一下发现可以把最大的点留到最后,这样不会加上它的贡献。枚举留下哪个点可以做到 \(\mathcal{O}(n^2\log n)\)。
尝试观察删掉一个点的影响,观察不出来。
Solution
观察整个过程,发现集合的大小一定是 \(1,1,\cdots,1,2,2,2,2,2,x\cdots,4,3,2,1\)。再观察贡献,发现之和最小值和最大值有关。
如果 \(|S|\geq 3\),则我们的方案是显而易见的:删去次大值。如果 \(|S|=2\) 问题就比较麻烦,注意到去除最后一个 \(2\),前面的 \(2\) 构成一个连续段,而这个连续段最后会剩下一个数,我们的决策相当于确定这个数是多少。可以发现这个数一定是最小值或者最大值,枚举是哪个暴力跑即可。
Conclusion
重点是两个观察。一是对操作的简化,简化之后变成了考虑每个深度的问题。第二是对操作和权值函数的进一步观察,它引导我们想到决策方案。
还有硬上 DS 做法,不太会。
P8350 [SDOI/SXOI2022] 进制转换
Solution
神秘折半题。
暴力枚举是 \(\mathcal{O}(n)\) 的。但是众所周知位运算具有相当的独立性,所以可以考虑 meet in the middle。那么我们枚举 \(m=x+3^{B}y\),并考虑它的二进制位,发现低位到高位的贡献至多为 \(1\),而枚举高位之后,低位二进制加法是卷积的形式,所以直接暴力 NTT 卷积即可。复杂度 \(\mathcal{O}(\sqrt{n\log n})\)。
另外一种做法是,从高位往低位 DP,设 \(f_{i,j,0/1}\) 表示填完三进制的后 \(i\) 位,二进制的 \(j\leq l_i\) 位的二进制表示,其中 \(l_i\) 满足 \(2^{l_i}>3^i\)。可以证明状态数是根号的。对于前一半,经过的状态数至多为根号。对于后一半,直接观察状态可以发现状态数为根号。所以这是一个正确的根号做法。
Analysis
对 meet in the middle 有了更深的理解。对于问题的两个相对独立的部分,可以分别处理,然后利用一些方法合并,达到优化的效果。此题用到了位的独立性。
P8362 [SNOI2022] 数位
Analysis
憨憨了。只会数位 DP 构造 \(a\),得到的做法大多是 \(\mathcal{O}(nk^t),t\geq 4\) 的。
Solution
数位 DP 显然是没有前途的,考虑对合法的 \(S\) 计数合法的 \(a\) 的方案数,相当于对所有合法的 \(S\) 计数:
需要满足组合数上标非负。考虑 DP 构造合法的 \(S\),则我们相当于要求一个下降幂的和,转成普通幂然后用第一类斯特林数转化回去。普通幂的话只需要处理在状态里面加一个 \(x\),用二项式定理展开即可。
Conclusion
比较有迷惑性,很容易想到数位构造 \(a\),防止陷进去的方法就是在最开始就建立起对问题的整体感知,先理解问题的整体结构再寻找突破口。
P6630 [ZJOI2020] 传统艺能
Analysis
开始考虑设 \(f_{i,j}\) 表示 \(i\) 时刻 \(j\) 的概率,本来准备强行做转移,但是各个变量之间都不是独立的啊。
然后想到观察区间的影响,发现两个叠起来的区间相当于操作三个区间,然后想到倒流,这样标记就不是动态的了,但是一个区间下推的时候需要考虑它的子树里面有没有标记,有的话就要继续下推,不好处理。
Solution
期望线性性拆开贡献,所以可以考虑从单个元素寻找突破口。观察可以发现一个元素被打上标记有两种情况:一种是它自己在区间定位中,一种是它的兄弟在区间定位中,而它的祖先中存在标记,进一步可以发现对于单个点我们只需要关注它祖先中是否有标记和它是否有标记即可,于是可以设 \(f_i\) 表示 \(i\) 时刻它有,\(g_i\) 表示祖先有,\(h_i\) 表示都有的方案,不难使用矩阵转移。
Conclusion
老老实实做观察吧。

浙公网安备 33010602011771号