9月杂题

[ABC310F] Make 10 Again

分母是 ai,只需求分子。

首先要发现投出了 10 以上的点数是无用的,所以只需考虑 10 以内的。

思考如何计数,发现转移依赖于前面的点数和的方案数,而且 10 很小,考虑状压 DP,设 fi,s 表示前 i 个骰子,状态为 s 的方案数,转移不表。

sM=211,所以时间复杂度 O(nM102)

[ARC174E] Existence Counting

怎么就没想到呢??一直想着直接计数,比较困难,正难则反,转化为:排列数 没出现 x 的排列数 字典序大于 P 的方案数 + 既没出现 x 字典序还大于 P 的方案数。转化后就比较基础了。

[ARC173C] Not Median

感觉还是不够。

直觉告诉我们,答案大多数都很小。

注意到答案很大的地方周围应该长这样 -+-+-+0-+-+-+,这告诉我们只需找到两个相邻的值又同时在 pi 一侧的就好了。

每个点都往左右扫,复杂度看似 O(n2),但是其实在 ix1,x2 之间的所有数答案一定是 3,这意味着每个数只会被扫一遍。所以时间复杂度 O(n)

[ABC281G] Farthest City

将所有点按最短路分层,每层的节点只能和相邻层还有层内的节点连边。设 fi,j 表示用了 i 个点,最后一层有 j 个点的方案。转移:

fi,j=k=1ijfij,k×(n1(ij)j)×2j(j1)2×(2k1)j

CF1476F Lanterns

典题,覆盖问题可以将状态设计成 fi 表示前 i 盏灯能覆盖的最长前缀。

转移分三类:

  • 前面不能覆盖到 i,直接不管 ifi=fi1
  • 前面能覆盖到 ifi=max(fi1,i+pi)
  • i 向左,找到一个 fjipi 最小的 j,然后 j+1i1 全部向右,fi=max{k+pk}

不知道为什么想这么久,明明这么简单。

[ARC154C] Roller

有 ARC182B 作为基础这题很容易想到做法,将相同的合并成一块,只需判断是否存在一个断点使得 ab 的子序列。

但是还需要空余的位置,可以是 ab 没出现的,可以是 b 中相邻的,也可以是 a 中相邻的。若没有空余位置则必须 a,b 完全相等。

细节一直写挂,数组还开小了。

P3214 [HNOI2011] 卡农

想不出来。

fi 表示选了 i 个子集且满足条件的方案。考虑容斥,为了满足和前面的 i1 个子集加在一起全是偶数,前面每种选法都唯一确定一种子集,方案数为 A2n1i1

再减去 i 为空的情况,方案数为 fi1(去掉 i 之后能满足条件)。

再减去 i 和前面相同的方案。去掉 ij 后也能满足条件,ji1 种取值,子集 i2n1(i2) 种取法,方案数为 fi2×(i1)×(2n+1i)

最后输出 fmm!

P3577 [POI2014] TUR-Tourism

在无向图搜索树上 DP,没见过。

由题得树的深度不超过 10,这启发我们用树上状压 DP(还是没见过)。

一个重要的性质:无向图 DFS 树上的非树边一定是回边,不存在横叉边。所以我们可以状压父亲的状态。

DP 过程较为复杂,不写。

P6381 『MdOI R2』Odyssey

通过质因数分解我们很容易判断是否能构成完美数对,但是信息在边上我们很难直接 DP。

但我们发现如果用哈希去表示每一条边,那么能与它配对的边的哈希值也是确定的。这启发我们设 fi,hi 表示以 i 为终点,最后一条边哈希值是 hi 的答案,时间复杂度 O(nlogn×11)

P8860 动态图连通性

很牛逼。

首先肯定要离线,然后多次询问的边只有第一次有用。

记边被询问的时间为 di,没询问的视作 di=Q+1。将 di 作为边的边权,那么就是要找一条路径,使得将路径上的边的权值从大到小排序,字典序最小。

类似 「The classic problem」一样用主席树维护最短路。

CF464D World of Darkraft

需要注意到 k 种装备地位相同,所以只需计算一种装备最后乘 k。设 fi,j 表示还剩 i 个怪兽,装备等级为 j 的期望。转移不表。

[ABC370F] Cake Division

不会倍增的菜鸟了属于是。

二分答案,记 fi 为从 i 开始的一个连续段的结尾 +1(即下一个连续段的开头),那么就是从 i 开始跳 kf 看终点是否满足条件。这显然倍增。

P7603 [THUPC2021] 鬼街

减半警报器。

一次灵异事件的发生可以暴力给所有质因子 +y,因为质因子个数很少。问题是什么时候统计答案。

对于一个 (x,y) 的监控,记加入时其质因子已经发生了 s 次灵异事件,响警报的条件是 pcntpy+s。转化成 Δcntpy。那肯定至少有一个 p 满足 Δcntpydx,我们将其设为阈值,当一个房间里有监控达到阈值时我们就拿出来 check 一下,这可以用优先队列实现。

如果 check 失败,我们让阈值变成 yΔcntpdx,然后重新加入优先队列。不难发现, 每次阈值至少减少 1dx,所以时间复杂度 O(m×dVlogVlogn)

[ARC171C] Swap on Tree

每棵子树最多 siz+1 种取值,且新的数是什么不重要。设 fx,t,0/1 表示以 x 为根的子树,与 x 相连的边断了几条边,和父亲的边是否断了的方案数。

fx,t,0fx,t1,0×fy,s,1×t+fx,t,0×fy,s,0

fx,t,1fx,t1,1×fy,s,1×t+fx,t,1×fy,s,0

初始化 fx,0,0=1fx,1,1=[x1]

P6383 『MdOI R2』Resurrection

其实就是联通块的根之间连边。

容易想到设 fx,i 表示 x 上面还有 i 个点可供选择的方案数,但是不会做转移。

因为 x 的选择会使得 i 的限制发生变化,而且 x 与儿子的谁先与父亲切断对转移也有影响。平常的树形 DP 依赖于儿子的状态,而这里对父亲也提出要求。

考虑分析图的性质,然后就发现儿子连的边一定不会与父亲连的边交叉,要不连父亲,要不连父亲连的点的上面。分析出这点,然后就可以枚举父亲连的点进行转移了。

P6009 [USACO20JAN] Non-Decreasing Subsequences P

静态区间查询,考虑猫树分治。

如何合并两个前后缀信息,记 gi,j 表示 [i,mid] 里以 j 结尾的不下降子序列数量。将值域放到状态里即可合并。

P3523 [POI2011] DYN-Dynamite

二分答案,如何判定?

转化成满足条件的最小覆盖。(用最少的点)

如果一个子树的根到这个子树的关键节点的最远距离 mid,那就可以选择根来覆盖整棵子树,但这样可能会重复覆盖,我们需要想一个方法减小多余的覆盖。因此我们设 fi 表示 i 距离它子树内关键节点的最远距离,gi 表示 i 到它子树内选定节点的最短距离。

初始化 fi=+gi=

转移 fi=max{fj+1}gi=min{gj+1}

还有一些情况需要特判

  • fi+gimid 时,i 子树已经无需覆盖,fi=
  • fi=mid 时,我们此时必须选择 i,则 fi=gi=0tot++
  • gi>middi=1 时,说明这棵子树不能被子孙覆盖,需要留给父亲,fi=max(fi,0)

贪心 + DP,根本做不出来。

P8292 [省选联考 2022] 卡牌

大于 V 的质数最多在每个卡牌里出现一次,可以特殊考虑,将 n 个数分组,依据是自己具有的大于 V 的质数。

对每个组预处理出 gs 表示组内凑出质数集合为 s 的质数的方案。

然后对组做 DP,设 fs,i 表示考虑了前 i 个组,凑出质数集合为 s 的方案数。如果该组的质数被询问了,则不能选空。否则可以选空。但是时间复杂度不对我去你的。

问题在于每个质数在不同的合法方案中会被选择不同次数,考虑正难则反,枚举不含的质数集合,使用容斥解决。设 fs,i 表示前 14 个质数不含的集合为 s,是第 i 个质数(i>14)的倍数的有多少个,可以预处理出来,时间复杂度 O(214ci)

P2150 [NOI2015] 寿司晚宴

仍然考虑设 fs,i 表示含有的前 8 个质因子集合为 s,且是第 i 个质因子的倍数有多少个。然后发现不太对啊。

正常考虑设 fs,t 表示 A 选了 s 集合的质因子,B 选了 t 集合的质因子的方案数。对于存在大质因子的数,对其内部做 DP,方法同上。

CF1810F M-tree

先考虑单次询问怎么做。可以二分答案,然后让每个点尽量往深度大的放。这样就可以得出答案 x 满足的充要条件就是 mxi=1nmai。所以答案就是 logmmai。这可以用线段树维护 m 进制实现。

P6576 [BalticOI 2017] Plus Minus

思考怎么才能固定整个矩阵,需要固定第一行和第一列。考虑什么时候才合法,发现必须第一行或者第一列是正负交错的。

然后你又发现,当第一行是交错的时候,每一行都是交错的。列同理。所以这时候就可以容斥计数了。

P5188 [COCI2009-2010#4] PALACINKE

这是一道挺困难的题。

首先不管买东西种类的限制,设 fu,i 表示走到 u 点,用了 i 时间的方案数。构造矩阵

Ans=[f1,i1,f2,i1,,f1,i,fi,2,,ans]

转移矩阵自己想。那么在没限制的时候可以直接矩阵快速幂进行转移。

现在如果有了限制那该怎么办?考虑容斥,用总方案数减去不合法的方案数。每次只保留是选定集合子集的边。时间复杂度 O(24n3logt)

反思:正常写出 DP 是带状态 s 的。因为这个东西难做所以才去想容斥。在没有了这个限制之后,再根据数据范围联想矩阵快速幂。有一些其它的做法,从一个经典问题:

一张 n 个点的有向图,求从 1 开始走恰好 t 条边,回到 1 的方案数。其中 n25,t109

引出。这个问题的解决方法就是矩阵快速幂。但是此题更为复杂,不是恰好,边权也不一定为 1,最后也要容斥。如何解决前两个问题??看 P3758P4159

P5664 [CSP-S2019] Emiya 家今天的饭

枚举菜的个数 k。先不管第三个条件,计算出用不同烹饪方法做出 k 道菜的方案数,然后容斥。

每次最多只有一种主要食材不满足条件。枚举主要食材 v。设 fi,j,t 表示前 i 种烹饪方法,用了 j 种,食材 v 用了 t 种的方案数。答案减去 fn,k,k/2+1k。时间复杂度 O(n3m),可以获得 84 分。

瓶颈在于计算不合法方案的时候。

我们发现 f 的第二维只是帮我们确定食材 v 是否比其它的多,但我们不关心具体是多少。于是我们可以设 fi,j 表示前 i 种烹饪方法,食材 v 比其它的多了 j 种。这样就是 O(n2m)

CF1980G Yasya and the Mysterious Tree

维护每个点到根的异或值 di,查询即查 dvdux 的最大值,若可以维护则可使用字典树查询。

不难发现修改操作只对深度为偶数的点产生影响,记录修改操作的总异或值 m。建立两棵字典树,分别维护偶数深度和奇数深度即可。

CF1994G Minecraft

考虑枚举每个位置填什么,一个关键的地方在于一个位置最多向前产生不超过 n 的进位(调和级数可证)。设 fi,j 表示第 i 位向 i+1 位产生了 j 的进位。

转移时根据填的数算出 1i1 位产生的进位,然后转移即可。

CF1823F Random Walk

将每个点的期望写出式子 Ei=\existedge(x,i)1degxEx。特殊的,Es 要加上常数项,不能从 Et 转移到 Ei,高斯消元,无法通过。

思考特殊性质,因为这是一棵树,于是考虑将每个点的期望写成和父亲有关的式子。

Ex=kxEfa,一开始有 Ex=1degfaEfa+y1degyEy 。将每个 fy 替换成 kyEx 即可。

CF1495D BFS Trees

先考虑只有一个点怎么做,以 x 为起点 bfs,然后将图分层,然后应该可以直接乘一些东西。

然后就不会了。

注意到若 ij 的最短路超过一条就无解。否则,必然最短路上的点都在生成树上。其余的,枚举其父亲,答案乘上满足条件的父亲个数即可。

CF1736E Swap and Take

观察到每个位置被覆盖的数的下标是单调递增的,于是设 fi,j,k 表示 i 这个位置被 j 覆盖了,用了 k 次交换。

  • ii1 一样,则 fi,j,k=fi1,j,k1+aj
  • 若不同,观察到此时 j 必须大于等于 i,不然为啥还会不同。于是 fi,j,k=maxp=1j1fi1,p,k(ji)+aj

想出了差不多,但还是差最后一点。感觉自己分类分的太过细致反而影响了思考。

CF1981E Turtle and Intersected Segments

一个关键的地方在于如何缩减边数规模。注意到若三条线段两两相交,假设 a1<a2<a3,那么因为 a3a1=a2a1+a3a2,所以只有后两条边有用,也就是只需连相邻的两条边。

考虑用扫描线维护这个过程,每条线段在 l 加入,在 r 删除。每次加入时与它 a 值的前驱、后继连边,边数降至 O(n),时间复杂度 O(nlogn)

CF1493E Enormous XOR

果然是一个结论题。

若最高位不相同则直接输出 n1

否则,我们希望选择奇数个,这样最高位才能为 1

我们已知模 4 等于 0,1,2,3 的四个数连续异或会变成 02i2i+1=1,所以选择其实是有限的,我们发现约束了条件的 (x,y),答案就是就只有 x,y,x1,y1 四种。显然当 y=r 时最优。此时再判断一下 x 取哪就好了。

P8819 [CSP-S 2022] 星战

如何判断一个点是否可以「实现反击」,其实就是形成基环森林。

「连续穿梭」则要求每个点出度为 1。所以只需全部点出度均为 1 就可以。

如何维护,使用和哈希

具体的,给每个点随机一个权值 w,我们维护所有边的起点构成的可重点集,只需判断集合 w 之和是否等于 i=1nwi 即可。

[ARC160F] Count Sorted Arrays

这它喵是人想出来的吗??

有一种 01 串的经典技巧:把小于等于 x 的设为 1,大于 x 的设为 0。那么一个排列就对应着 n+1 个 01 串。一个排列有序当且仅当这 n+1 个 01 串都有序。01 串在变化的时候,最多有一个 01

假设我们得到了 01 串 i 经过操作后得到的新串 fi。考虑对 01 串计数,设 dpi 表示已经选了 popcount(i)01 串,最后一个是 i 的方案数。转移即 dpidpi2j。但要保证 i 现在是有序的,即 fi 所有的 1 都在最前面。

每次操作,若所有排列的 x,y 都有序了就不操作。时间复杂度 O(n32n)

[ABC328G] Cut and Reorder

套路的设 fs 表示 s 集合里的数匹配了 b 的前 popcount(s) 位,但是我不会转移,觉得交换操作带来的影响剩下的数的相对顺序很难搞。

但其实我们肯定只用一次交换操作就达到最优的排列,所以我们可以直接 DP 维护这个过程。每次找到一段连续区间接上 s。可以证明时间复杂度是 O(n2n)

CF1530F Bingo

容易想到容斥,计算满足所有行列对角线都至少有 10 的情况,于是就有了 O(n4n) 的做法。

先考虑只有列的情况。再次容斥,用全部情况减去至少一列全为 1 的概率,再加上至少两列全为 1 的概率……

然后在计算列的同时枚举行计算行的概率。设 gi,s 表示第 is 集合位置为 1 的概率,然后我们只需要保证行不全为 1 就行了,那么一行的贡献就是 gi,sgi,2n1

枚举对角线的状态,时间复杂度 O(2n+2n)

[ABC319G] Counting Shortest Paths

想着先求出最短路,但是只会 O(n2)

想到用 set 维护未被访问的点,但是没想到可以只走要删除的边然后再求补集。然后这样就可以求出最短路。

然后按照最短路分层,先让每个 v 加上满足 disu+1=disv 的所有 fu,然后再减去多余的。

时间复杂度 O(mlogn)

P11071 「QMSOI R1」 Distorted Fate

考虑线段树维护区间内的数二进制下每一位的 1 个数。

修改操作相当于将 01 个数反转。

查询操作考虑每一位的贡献,二分出第一个 i 使得 cnt1(l,i)1,贡献就是 2i×(ri+1)

时间复杂度 O(nlogn×30)。空间复杂度貌似过不了但还是过了。

进一步的优化是,维护每一位的与、或,然后也比较简单。

P9220 「TAOI-1」椎名真昼

博弈论!

发现最多一个回合即可确定胜负。

A 赢就是要找一个黑点,操作一次就全白,可以 tarjan + 拓扑 + 搜索实现。

B 赢只有三种情况:

  • 全白。
  • 两个孤立黑点。
  • 一个黑点连向一个白点。

P9871 [NOIP2023] 天天爱打卡

fi,0/1 表示到第 i 天,这一天不跑/随便的最高能量。枚举一个跑步连续段的起点 j,然后 fj1,0+val(i,j)(ij+1)×dfi,1。其中 val(i,j) 表示所有满足 ixkykjvk 和。使用线段树优化,每次加入一个 i 时给 [0,i) 全部减去 d,然后给 rk=i 的所有 j<lkj 全部加上 vk。然后查询 [ik,i) 的最大值转移到 fi,1,再将 fi,0 加到线段树。时间复杂度 O(nlogn)

发现只有段上的点有用,对端点离散化后套用上述做法,时间复杂度 O(mlogm)

P6879 [JOI 2020 Final] スタンプラリー 3

一定要看数据范围做题

fi,j,0/1 表示区间 [i,j] 到达 i/j 的最小时间,但是不好转移,一开始想二分收集的数量,但是收集的雕像不一定连续。然后就不知道怎么处理时间和数量的依赖了。

发现这种状态的转移一般是 O(1) 的,而 n200,于是我们可以直接把数量放进状态里,这样就是 O(n3) 的状态,转移 O(1),可以通过。

P10430 [JOISC 2024 Day1] 鱼 3

问题即用最少的单点减 D 次数 使得 clr 单调不降。

暴力做法就是从 rl 直接贪心扫一遍。

考虑将询问离线,然后扫描线,每次加入一个 r 时就往前去暴力做。观察到如果我们更新了一对相邻的数,那之后它们的差不会变化。于是我们可以拿一个栈维护还没有更新过的地方,对一段连续段使用区间减法。这样复杂度均摊 O(nlogn)

反思:好像啥都可以离线扫描线。

P8162 [JOI 2022 Final] 让我们赢得选举

有一个直观的想法,枚举协作者数量 t,然后选 bit 小的城市找协作者,再从剩下的选 aikti 小的来演讲。

但这是有问题的,可能一个 bi 很小的地方 ai 极其小。

于是我们加入一些 DP 来修改贪心。

fi,j 表示前 i 个地方,选了 j 个协作者,其余地方直接演讲的最小时间。枚举总共协作者数量 t 这个东西是好 DP 的。然后再加上后面的贡献就好了。时间复杂度 O(n3)

反思:当贪心出现问题的时候,尝试使用 DP 来进行修正。

P9522 [JOISC2022] 错误拼写

牛魔计数题使我旋转。

主要说一下分析思路:

根据字典序的比较方式我们可以转化一下 TAj<TBj 这个条件。我们现在只考虑严格小于的情况。

字典序暗示我们要从后往前 DP,于是设 fi,j 表示 si=j 的方案数。然后考虑从 fi,j 转移过来,思考转移的约束。

这个约束就是对于一段 [A,B] 里面的 i,对 i<A 都要少掉一段贡献,这段贡献和 j 有关。

于是设 hj 表示 i+1nf,j 的贡献。每次移动 i 的时候更新 hj。用链表维护,时间复杂度 O(n||)

计数题好难。

長距離バス

发现每次赶走的人一定是一段区间。而这个区间的末尾必须紧跟着一个服务区,不然后面的人会被影响。

fi 表示前 i 个人的最小代价。

如果不下车,fi=fi1+W×(XT+[DiXmodT])

如果下车,考虑枚举这段下车区间的上一个人 j,则 fi=minfj+sumC(j+1,i)+W×mti×(ij)。其中 mti 表示第 i 个人最快在啥时候可以下车。

对第二类转移使用斜率优化即可。

P9331 [JOISC 2023 Day1] Passport

线段树优化建图。

i[li,ri] 连边。有种想法是将左端点和右端点分开考虑,但是一步可能同时向左右端点扩展,然后就不会了。

接下来就是注意力惊人了,我们注意到,在最优方案中,存在一个时刻,该时刻之前每一步同时向左右扩展,该时刻之后每一步只向一边扩展。

所以设 disx 表示从 x 分别向左右扩展加起来的最小护照,答案就是 mindisj+d(j,i)

建出反图,跑两次 dij 可以求出 disx,然后新建源点向 idisi 的边,再跑一次最短路。

posted @   xishanmeigao  阅读(16)  评论(0编辑  收藏  举报
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示