Typesetting math: 0%

『DP』Record

Pig 的 DP 题!然而做了也不会像 Pig 一样聪明(

可能不会按照难度排序,但大多数 CF 题都有难度标签,可以参考。

可以在博客园查看。

TODO LIST : P3780 P6596TODO LIST : P3780 P6596

一般列入 TODO LIST 的应该都是懒得写题解的题了。

SIZE:79.9 KB(2024/2/27)

普通 dp#

一些纯思维的 dp,可能比较套路,也有可能不好分类所以放在这里。

CF1271D Portals#

Difficulty : 2100

对于一个 u,记录 ltu 表示最大的能够到达它的点 v,考虑按照 lt1n 进行排序。

同时开一个指针 p,表示当前可控制的城堡。

dpi,j 表示到第 i 个城堡剩下 j 个士兵的最大得分。

如果到了 i 什么都不做,那么显然 dpi,j+bidpi1,j;然后你继续移动指针 p,只要 ltp=i,即可转移 dpi,jdpi,j+1+cp

不难看出 ci 为排序后城堡 i 的价值,和题面中的不一样。

CF213C Relay Race#

Difficulty : 2000

按照套路,跑两次路线就相当于两个人一起从 (1,1) 出发。

然后两个人在某一时刻一定不在对方的历史路线上,因为步数相等。

步数相等还有一个好处,就是可以用来做状态,如果已知步数 i,两个人走到的行数 j,k,那么两个人的坐标也是可以算的,显然就是 (j,ij+1) 以及 (k,ik+1)

于是令 dpi,j,k 表示上述状态,则:

dpi,j,kdpi1,j,k

dpi,j,kdpi1,j1,k

dpi,j,kdpi1,j,k1

dpi,j,kdpi1,j1,k1

正常做的话空间 O(n3),有点危险。

然后第一维是可以滚掉的,所以空间 O(n2),时间 O(n3)

CF459E Pashmak and Graph#

Difficulty : 1900

考虑一般的不降子段咋做,n3×105

dpi 为以 i 结尾连续不降子段最长长度:

dpidpi1+[ai1ai]

当然也有一种方法,将 ai 从小到大排序,记排序后 ai 在原数组中对应下标为 pidppidppi1+1,答案为 max{dpi}

这里用第二种方法,放到图上。

先按照边权从小到大排序,然后考虑转移。

因为题目要求严格递增,而直接转移的话可能会使得连在一起相同权值的边也被算进去,所以要先把相同权值的边对应两点的 dp 值存下来,然后用这个数组转移 dp 即可。

CF337D Book of Evil#

Difficulty : 2000

感觉这是前面最思维的一道题(?

以下有怪物的点记为关键点。

记录 u 子树内关键点离 u 最远和次远距离(两个关键点不在 u 的同一个儿子的子树内),记为 dpu,0/1

考虑从叶子向根转移,显然有:

  • dpu,1dpu,0,dpu,0dpv,0+1   (dpv,0+1>dpu,0)
  • dpu,1=max{dpu,1,dpv,0+1}       (otherwise)

然后令 disuu子树外关键点距离 u 的最远距离,考虑从根到叶子转移:

  • 如果 dpu,0dpv,0 转移而来,说明 u 子树内离 u 最远的关键点在子树 v 内,于是我们需要找次远的那个点,因为根据 dp 的定义,次远点和最远点不在 u 的同一个儿子的子树内,所以 disvmax{disu+1,dpu,1+1}
  • 如果 dpu,0 不由 dpv,0 转移而来,那么还是在 u 子树内,v 的最远距离就是它到距离 u 最远的关键点的距离,disvmax{disu+1,dpu,0+1}

然后最后遍历每一个节点,如果当前节点为根节点,只需要满足 dpu,0d 即可对答案贡献;如果当前节点不为根节点,需要满足 dpu,0,disud

复杂度 O(n)

CF710E Generate a String#

Difficulty : 2000

首先如果加了一个字符,然后再删肯定不优。

于是只有倍长后才能删去一个字符,此时长度一定为奇数。

所以 fimin{fi1+x,fi/2+y},2i 或者 fimin{fi1+x,f(i+1)/2+y+x},2i

ARC065D シャッフル / Shuffling#

Difficulty : 2652

鬼知道这个难度是怎么搞出来的……不过这题确实挺神的。

n,m3000,明摆着 O(n2)

fi,j 表示考虑前 i 位填了 j1 的方案数。

显然有 fi,jfi1,j1+fi1,j,关键是转移上下界如何确定,因为有些地方是不能放 1 的。

于是可以预处理出每个 i,能随意排列到的最右端点 ri;以及每个前缀 1 的个数 ci

则转移中 j 的下界的话你当然希望前 i 个位尽量放 0,所以先把 iri 尽量全放 1,于是 lj=max{0,i(ricri)}

对于上界,你也当然希望前 i 位尽量放 1,所以先把 rci1 都放 i 里面,于是 ri=min{i,rci}

AC 记录

CF883I Photo Processing#

Difficulty : 1900

dp 与二分结合。

最大价值最小,考虑二分答案。

ai 从小到大排序的话,你会发现你选的组一定是连续的,不然不优。

于是令 dpi 表示仅考虑 1i 一共 i 个数是否有可行的分组。

那么 dpidpj(j{0,1,...,im},aiaj+1lim)

lim 即为你二分的答案。

但这样显然过不了,考虑优化,首先你发现最小的 j 使得 aiajlim 是单调不降的,j 的上限也是单增的,滑动窗口即可。

就是搞一个双向队列,如果 dpimtrue 的话就从右边加进来 im,然后一直弹出左边不符合的(即不满足 aiaj+1lim),最后如果队列里面还剩下可以转移的位置那么 dpi=1 了。

由于左指针的移动次数最多 O(n),所以 check 的复杂度是 O(n) 的。

复杂度 O(nlogn)

CF1187E Tree Painting#

Difficulty : 2100

无脑题,以后尽量避免点进这种题目,否则会变笨。

设第一个黑点为树的根节点,当「根」确定了不难发现同深度的染色互不干扰,因为它们的父亲都染了色,于是它们不在一个连通块中。

不难发现染 u 的权值为 subtree(u)

然后换根 dp 即可。

POI2006 MIS-Teddies#

简单 dp 题。

我们只关心个数和最后 2 位,大力设六维 fi,j,p,q,x,y,每次转移枚举 4 种情况,判断是否合法然后贡献即可。

复杂度 O(n4b3)b 为泰迪熊的种数即 4。可能需要滚动数组,反正我没有高超的卡常技巧。

CF852H Bob and stages#

  • Difficulty : 3000

考虑到 nk 都很小,可以先将所有点对于 x,y 坐标排序,枚举答案凸包最左边那个点 p。然后设 fi,j 表示走了 i 步,目前位于 j 点的最大面积,答案就是 fk,p

考虑从 fi1,x 转移到 fi,y,此时 dp 受如下限制影响:

  • 此时加入点 y 后,路径上的点的集合仍然是个凸多边形
  • 加入点 y 后,路径上的点的集合构成的凸多边形内部不包含任何给定的点。

由于任意的转移前后都满足限制,考虑将凸包拆分成若干个以 p 为顶点的三角形,每次相当于加入以 p,x,y 为顶点的三角形,如果我们是逆时针加入点,转换限制如下:

  • xy 的直线要比 x 转移过来的直线往左偏。
  • p,x,y 为顶点的三角形不包含其它点。

第一个限制满足了凸多边形的性质,第二个限制归纳满足了凸包内部没有点的限制。

但是此时又有一个问题:如何确定 x 转移过来的直线的斜率。一个简单的想法是再加一维状态 k 表示第 i 步是由 k 走到 j,但是复杂度 O(n4k),寄了。

不妨优化转移,考虑对转移的边进行极角排序,那么后面的边就一定能从前面的边转移过来了。于是排序后依次枚举转移边,再枚举步数,复杂度就是 O(n3k) 的了,足以通过本题。

有一个细节问题,就是 px 向量如果 x 坐标为 0y<0,那么极角排序时会把它放到开头,此时对于所有点排序时 x 坐标相同应将 y 坐标大的放前面,否则转移不到。

状压 dp#

CF839E Mother of Dragons#

Difficulty : 2700

发现若 u,v 不通过一条边联通且 wN(u)swwN(v)sw,那么把 sv 加给 su 一定不劣。

所以最后答案一定是一个连通完全子图,设其大小为 m,那么答案就是 (m2)(km)2

不难发现这东西关于 m 单调递增,所以求出最大团大小即可。

典型的做法是折半,可以 O(n) 判断一个点集的导出子图是否是团,枚举半边的一个团 S ,另一半预处理 f(T) 表示点集 T 导出子图中的最大团大小,然后求出半边点都能连到的另一半的点的集合 T,求 |S|+f(T) 的最大值即可。

复杂度 O(n2n2)

P2150 [NOI2015] 寿司晚宴#

典。

考虑 n30,其以内只有 10 个质数,于是考虑状压。

dpi,j,k 为考虑到第 i 个寿司,两个人选的寿司的质因数情况或起来分别为 j,k 的方案数。

显然 dpi,j,k or st(i)dpi1,j,k (st(i) and j = 0) 或者 dpi,j or st(i),kdpi1,j,k(st(i) and k = 0)

然后可以滚动数组,但是没有必要,反正过不了,复杂度 O(220n)

然后考虑 n500,此时 n<30,这表明除了 30 的质因子之外,n 可能有且仅有 1 个大于 30 的大质因子。

dp 含义不变,记录 dp1,dp2 分别表示这个大质因子在分别两个人那边的方案数量。

求出 2n 每个数的大质因子,然后按其升序排序,以便分段考虑。

在大质因子都相同的一段内,dp1,dp2 的转移与上述 dp 类似,不过你只能选定一个人进行转移,比如如果你选 dp1i,j,k or st(i)dp1i,j,k(st(i) and j=0),那么 dp2 就必须把数搞到 j 上面,原因可由 dp1,dp2 的定义得到。

然后如果跨段的话更新 dpi,j,k=dp1i,j,k+dp2i,j,kdppr,j,kpr 为上一段末尾的下标),即减去两个人都没有选大质因子的情况。

滚掉第一维,最后的答案就是 dpj,k

CF510D Fox And Jumping#

Difficulty : 1900

还是典。

由于 2×3×5×7×11×13×17×19×23=223092870,所以 109 以内的数其质因子不超过 9 个。

所以如果我们先钦定选一张卡 k 的话,只用考虑剩下所有卡中对于被 k 这不超过 9 个质因子的整除情况。

因为在选卡牌的过程中 gcd 单调不增,所以令 dpst 表示当前 gcd 状态为 st 的最小代价,首先 dpsti=cistii 对于钦定卡牌 k 的质因数状态)。

所以如果选了 i 卡牌,当前质因数状态为 s,那么:

dps&stidps+ci

求质因子的话根号分解质因数即可,总复杂度 O(nm+29n2)m 为最大的 li

SDOI2009 Bill的挑战#

忽略容斥,无脑状压。预处理出 tri,j(ilen,j25) 表示 Ti 位填 j 能够匹配的状态(这里的“状态”指 02n1 的二进制数)。令 dpi,st 表示第 i 位填完,匹配状态位 st 的方案数,dp0,2n1=1

dpi,stdpi+1,sttri+1,p 转移,枚举 i,st,p 即可。

复杂度 O(26m2n)m 为字符串长度。

CF11D A Simple Task#

Difficulty : 2200

经典状压。

dpi,st 表示走到点 i,经过点的状态为 st 的方案数。

显然初始时 dpi,2i=1。为了防止算重,我们钦定 st 状态中最低的那一位即 lowbit(st) 为环的起点,

对于一条边 (u,v)dpv,st|2vdpu,st(vst),否则如果 2v=lowbit(st),就统计答案。

由于会算重两个点组成的环的情况,所以答案要减去 m

由于一个环顺时针逆时针被算了两次,所以答案还要除 2

复杂度 O(2nm) 或者 O(2nn2)

Xmas Contest 2021 D Determinant?#

Amitsur-Levitzki 定理,当 n2k 时,答案为 0 矩阵。

否则我们考虑答案矩阵的某一位 bi,j,其必然由某些路径 i=p0p1 pn=j 贡献而来,一条路径的贡献为 sgn(σ)ni=1Aσ(i),pi1,pi

于是直接 dp,类似状压求行列式,记录当前 σ 中的 A 矩阵集合,dp 的值为一个矩阵,表示目前的 sgn(σ)Aσ(i)。每次转移进行一次矩阵乘法。复杂度 O(2nnk3)=O(4kk4)

PKUSC2018 最大前缀和#

这个期望显然是诈骗,即统计每种排列最大前缀和之和。

对于某个排列 a,令 s(l,r)=rk=lak。考虑前缀 [1,i] 成为答案的充要条件

  • 1<ji,s(j,i)0,否则可以去掉这段。
  • j>i,s(i+1,j)<0,否则加上这段不劣(钦定取的是最大并且最靠后的前缀)。

那么可以考虑状压,设 fS 为选择 S 这个集合作为 [i+1,n] 并且满足第 2 个条件的方案数,设 gS 为选择 S 这个集合作为 [2,i] 并且满足第 1 个条件的方案数。转移的话就考虑哪个数塞到开头/结尾即可。

统计答案时枚举第 1 位填 ai,然后枚举集合 S 作为合法的前缀,计算方案数用 gSfU(S{i}) 即可,即:

ans=ni=1SU{i}(kS{i}ak)gSfU(S{i})

复杂度 O(n2n)

ZJOI2015 地震后的幻想乡#

Hint 是 n[0,1] 之间均匀随机分布的数的第 k 小值的期望为 kn+1,证明可见这篇博客

考虑 Kruskal 求最小生成树的过程。从小到大加入每条边,当加入第 i 一条边时整张图联通了,那么 wi 就是生成树上边权最大值。

这启示我们钦定一个边集 S,包含了前 |S| 小的边权,加入第 |S| 条边时整张图刚好联通。由提示知道此时 S 对答案的贡献为 |S|m+1。考虑统计大小为 i 的符合 |S|=i 的方案数,除以总方案 (mi) 即可得到概率。

难搞的限制在于加入第 i 条边时恰好联通,考虑容斥,转化成加入第 i 条边 Si 前不连通的方案数减去加入第 i 条边后不连通的方案数。于是概率就变成了加入 Si 前不连通的概率减去加入 Si 后不连通的概率。

于是只需要求出加入 Si不连通的方案数。考虑 dp,设 fT,i 为考虑点集 T,其中连了 i 条边,点集内不连通的方案数;为了方便转移,维护 gT,i 为考虑点集 T,连 i 条边,联通的方案数。显然有 fT,i+gT,i=(dTi)dT 表示点集 T 导出子图中边的个数,即 |E(G(T))|

考虑转移,由于不能联通,枚举一个连通块 TT 及其内部边数,连通块外任意连边,那么:

fS,i=TTdTj=0gT,j(dTTij)

但是这样做有个问题,对于对于不同的连通块可能会算重。所以在 T 中钦定一个点 kTkT

答案就是 m+1k=1km+1(fU,k1(mk1)fU,k(mk))U 为全集。可以化简但没必要,复杂度 O(3nm2)

CF1193A Amusement Park#

发现一个 DAG 所有边反转后仍然是 DAG,所以一个反转了 c 次的反转方案唯一对应了一个反转了 mc 次的方案。两种方贡献案之和为 m,所以设 s 为给无向图定向成为 DAG 的方案数,答案就是 s×m2

于是问题转化为求给一张无向图边定向,使得定向后成为 DAG 的方案数。考虑状压 dp,令 fS 为给点集 S 的导出子图定向后为 DAG 的方案数。

考虑 DAG 中一定有出度为 0 的独立集,同时删去这个集合后图仍为 DAG,所以枚举独立集 T,钦定其出度为 0

fS=TS,TfSTg(|T|)[Tindependent set]

g(n) 为容斥系数,因为会算重。由于一个大小为 n 的点集 T 会被它的每个非空子集计算一次,而我们要求 T 的贡献恰好为 1

1=ni=1(ni)g(i)

大眼观察得:g(1)=1,g(2)=1,g(3)=1,。我们猜测 g(n)=(1)n+1

mi=1(ni)(1)i+1=(ni=0(ni)(1)i1)=((1+1)n1)=1

所以取 g(n)=(1)n+1 即可:

fS=TS,T(1)|T|+1fST[Tindependent set]

暴力算是 O(3n) 的,在线做子集卷积即可达到 O(n22n)

计数 | 期望 | 概率 dp#

CF895C Square Subsets#

Difficulty : 2000

dp 与排列组合/数学结合。

首先看到 ai70,并且平方数仅考虑质因数个数的奇偶性,所以考虑压缩质因数状态。打表发现 70 以内只有 19 个质数,于是可做。

dpi,st(i{1,2,...,70},st{0,1,...,2191}) 表示当前考虑到 i,且选完质因数个数奇偶状态变为 st 的方案数。

于是如果选奇数个 i,则 dpi,stdplt,st xor st(i)×(C1c(i)+C3c(i)+C5c(i)+...);如果选偶数个 i,那么 dpi,stdplt,st×(C2c(i)+C4c(i)+C6c(i)+...)

st(i) 表示 i 的质因数个数奇偶状态,lt 表示上一个在原数列中存在的 ic(i) 表示原数列中 i 的个数,这些都是转移前可以求出来的。

注意到 C1c(i)+C3c(i)+C5c(i)+...=C2c(i)+C4c(i)+C6c(i)+...=2c(i)1,于是:

dpi,st(dplt,st xor st(i)+dplt,st)×2c(i)1

然后答案就是 dplt,01,去掉全都不取的情况。

滚一滚,空间 O(2w+n),时间 O(w2w)w=19

CF893E Counting Arrays#

Difficulty : 2000

还是 dp 和数学结合。

根据小学套路,前 y1 个符号可以先忽略,留在第 y 个调整,所以符号共有 2y1 种。

所以以下只需要考虑正整数的情况,发现由于乘积 106,最多只能填 19 个非 1 的正整数,于是考虑 dp

dpi,j(i19,j106) 表示长度为 i 的不含 1 的正整数列,乘积为 j 的方案数。

显然有:

dpi,j=kj,k<jdpi1,k

注意到不好枚举每个数的因数,我们考虑枚举每个因数的倍数,那复杂度就变成了一个调和级数。

考虑把 1 加进去,枚举非 1 项个数 i,将 yi1 插进 i+1 个空里面,和分组同理,方案数为 (yi+i+11i+11)=(yi)

于是答案就是:

2y1min(y,19)i=1(yi)dpi,x

复杂度 O(nlog2n+qlogn)

NOIP2016 提高组 换教室#

期望好题。

考虑到申请次数有限制,那就需要纳入 dp 状态了。

dpi,j,0/1 表示考虑前 i 个时刻,包含 i 在内总共申请了 j 次,第 i 次申/不申请的最小期望。

然后由于转移时从 u 走到 v 一定是走最短路最优,所以可以先用 floyd O(v3) 预处理出任意两个点的最短路。

考虑转移:

i 时刻不申请,转移 dpi,j,0,若 i1 时刻也不申请,dpi,j,0dpi1,j,0+disci,ci1;若第 i1 时刻申请了,根据概率知识有 dpi,j,0dpi1,j,1+(1pi1)disci,ci1+pi1disci,di1

同理,若 i 时刻申请,转移 dpi,j,1,若 i1 时刻不申请,dpi,j,1dpi,j1,0+(1pi)disci,ci1+pidisdi,ci1,若 i1 时刻申请了,则需要分四种情况:dpi,j,1dpi,j1,1+(1pi)(1pi1)disci,ci1+(1pi)pi1disci,di1+(1pi1)pidisdi,ci1+pipi1disdi,di1

初始状态 dp1,0,0=dp1,1,1=0

复杂度 O(nm+v3)

SHOI2012 随机树#

期望 dp

考虑第 1 个询问,我们令 fi 表示叶子节点数为 i 时,叶节点的平均深度期望。然后我们随机抽一个叶子节点进行展开,此时对叶子节点深度和的贡献为 2(fi+1)fi=fi+2,即 fi+1=ifi+fi2i+1=fi2i+1,初始时 f1=0

再考虑第 2 个询问。考虑到 E(x)=p(i)ip(i)n 个叶子节点,树深度为 i 的概率,考虑一个后缀和,我们设 gi,ji 个叶子节点,树的深度 depj 的概率,答案即为 ni=1gn,i

对于转移,我们可以枚举左右子树大小,即:

gi,j=1i1i1k=1gk,j1+gik,j1gk,j1×gik,j1

因为会有算重(两个子树深度均大于等于 j1)的情况,转移还减去了 gk,j1×gik,j1

复杂度 O(n3)

Luogu3412 仓鼠找sugar II#

fu 表示从 ufa(u) 的期望步数,gufa(u)u 的期望步数,duu 的度数。

那么显然有:

fu=1du(1+vson(u)(1+fv+fu))

移项后得到 fu=du+vson(u)fv

gu 的话要分两类:

  • fa(u)root

gu=1dfa(u)(1+(1+gfa(u)+gu)+vson(fa(u)){u}(1+fv+gu))

  • fa(u)=root

gu=1dfa(u)(1+vson(fa(u)){u}(1+fv+gu))

由于 groot=0,移项后均能得到 gu=ffa(u)+gfa(u)fu

然后就可以预处理出 f,g 了。

考虑所有路径 uv,统计从 u 走到 v 的期望步数,再除去 n2。一条 uv 的路径,将其贡献与 vu 的路径合并。记一条边 e:(u,fa(u)) 的权值为 we=fu+gulca(u,v)k,就变成了经典问题。注意到:

(u,v)(p[uk]{k}fp+p[kv]{k}gp)=u,v(无序)(p[uv](fp+gp)fkgk)=e:(u,fa(u))weszu(nszu)

2 步为考虑每条边对答案的贡献,即为穿过这条边的路径条数。

然后就很好做了。复杂度 O(n)

CF605E Intergalaxy Trips#

Difficulty : 2700

dpiin (不留在 i 原地)的期望天数,显然 dpn=0,并考虑两个简单的结论:

  • dpu 每次转移来的点一定是所有 u 能到中 dp 值最小的点。
  • dpu<dpv 并且 (u,v)Eu 一定不由 v 转移而来。

这和最短路很像,启示使用类似求最短路的方法求解原问题,虽然我知道直接这样写出来很蠢。

考虑现在转移 ii 出边形成的邻域 dp 值从小按大排序形成序列 a

  • 首先如果 aj 能转移到 i,说明比 aj 小的 ak<aj 都没有从 i 到达它的边,概率为 j1k=1(1pi,ak)
  • 其次如果要从 aj 转移到 i,那么 (i,aj) 这条边存在的概率为 pi,aj
  • 考虑 aj 转移到 i 的贡献,肯定有一个 dpaj,然后由于 dp 的定义,还要考虑自己走自己的情况。

所以转移:

dpi=mj=1dpaj1nk=1(1paj,ak)pi,ajj1k=1(1pi,ak)+1

CF398B Painting The Wall#

首先可以先去掉已经符合条件的行或者列,然后设 dpi,j 表示还剩 ij 列的操作次数的期望。

那么可以分情况讨论:

  • 如果涂色格所在行列均没有被染色,dpi,jdpi1,j1×ijn2
  • 如果仅所在行没被染色,dpi,jdpi1,j×i(nj)n2
  • 如果仅所在列没被染色,dpi,jdpi,j1×(ni)jn2
  • 如果该点早就被染色了,dpi,jdpi1,j1×(ni)(nj)n2

我们发现转移过程有自己转移自己的情况,对于这种操作无限的题目可以求解方程,在此题中我们求出 dpi,j 的转移式即可。

移项后得:

dpi,j=ijdpi1,j1+i(nj)dpi1,j+(ni)jdpi,j1+n2n2(ni)(nj)

O(n2) 转移即可。边界显然是调和级数前缀和(经典结论)。

CF123E Maze#

Difficulty : 2500

考虑 u 做起点时,树上每个点对答案的贡献。

先把 u 当作根,然后假设当前终点为 v,先计算这条路径的期望长度:

  • 对于 v 子树内的边,显然不会计入路径当中,贡献为 0
  • 对于 uv 路径上的边,显然只会经过 1 次,所以贡献为 1
  • 对于 v 子树外并且不在 uv 路径上的边,我们就可以选择经过/不经过,如果经过的话从上到下搜索再从下到上回溯会产生 2 的贡献,综合两种情况这样的边的贡献仍然为 1

所以 (u,v) 对答案的贡献应该是 nszv,而选中这个路径的概率为 puqv(令 pii 为起点的概率,qii 为终点的概率),即答案应为:

uvpuqv(nszu,v)

不难看出 szu,v 表示以 u 为根时 v 子树的大小。

现在我们考虑换根 dp,令 cur=vqv(nszv)

当根 uu 时:

  • szunszu
  • szun
  • curcur(nszu)qu+szuqu

每次 ansans+cur×pu 换根即可。

P3600 随机数生成器#

水题一道。

如果一个区间 [l,r][l,r],那么 [l,r] 这个区间对最大值没有影响,可以删去。于是剩下的 q 个区间将会互不包含。可以排序后用单调栈实现。

由期望公式 E(ans)=xi=1i×pipiq 个询问的最大值为 i 的概率。

考虑变式,pi 做一个前缀和变成 xi=1i×(pipi1)pi 为最大值 i 的概率。

然后不难发现求最大值 i 的概率 pi 即求最大值 i 的方案数 qi ,因为这个方案数再除去 xn 就是概率了。

最大值 i 代表每个区间的最小值都 i,即每个区间都至少有一个 i 的数。不妨枚举 n 个数中 i 的数的数量,那么 qi=nj=1gjij(xi)jgi 为在 1n 里面塞 i 个数,使得每个区间都至少包含一个数的方案数。

然后就做完了,直接 dp:令 fi,j 表示 1i 选了 j 个点,第 i 个点必选,所有左端点 i 的区间都至少包含一个选的点的方案数。转移的时候考虑枚举上一个被选的点,如果能转移就说明这两个点之间没有区间。

可以预处理覆盖 i 点的最左区间 lpi 和最右区间 rpi,由于我们给区间排过序,所以转移的条件即 rpk+1lpk。即 fi,j=rpk+1lpkfk,j1

不难发现 lp,rp 都有单调性,能够转移过来的 k 是一个区间,可以双指针维护左界,右界其实就是 i1。可以前缀和优化求 f

然后 gi 就可以求了,枚举最后选的那个点:gi=rpj=qfj,i

然后就随便做了。

P4707 重返现世#

首先要知道一个叫 Min-Max 容斥的东西,然后我们要用它的加强版,即 拓展 Min-Max 容斥

mink(S)=TS(|T|1k1)(1)|T|kmax(T)

maxk(S)=TS(|T|1k1)(1)|T|kmin(T)

上面所有的式子都是对期望成立的,即:

E(mink(S))=TS(|T|1k1)(1)|T|kE(max(T))

E(maxk(S))=TS(|T|1k1)(1)|T|kE(min(T))

如果你没看懂的话,可以去隔壁博客

介绍完前置知识就可以回到题目了。我们可以把题目看作每个原料有一个生成时间,即求第 nk+1 大的期望值。为了简化式子,以下令 knk+1,显然 k11,并且求的是第 k 大的期望。

套用拓展 Min-Max 容斥,把前 k 大转换成最小:

E(maxk(S))=TS(|T|1k1)(1)|T|kE(min(T))

显然对于每一种 T,可以把 T 中的原料看成一类,其它的看作另一类,那么抽到 T 中原料的概率显然就是 PT=iTpim,由于E(min(T)) 表示第一次抽到 T 中原料的期望时间,所以由简单期望知识我们知道 E(min(T))=1PT=miTpi

所以

ansk=TS(|T|1k1)(1)|T|kmiTpi=mTS(|T|1k1)(1)|T|kiTpi

然后考虑 dp,由于 km 都很小,于是可以纳入状态,令 dpi,j,k 表示当前考虑前 i 种原料,iTpi=j 的时候 ansk×j 的值。

转移的话,其实非常显然。

  • 首先你可以不取 idpi,j,kdpi1,j,k
  • 其次,如果你选了 i,那么:

(|T|1k1)(1)|T|k=(|T|2k2)(1)(|T|2)(k2)(|T|2k1)(1)(|T|2)(k1)

于是这种情况可以从 dpi1,jpi,kdpi1,jpk,k1 转移过来。

总的转移式子就是:

dpi,j,k=dpi1,j,k+dpi1,jpi,k1dpi1,jpi,k

O(nmk) 转移即可,但是注意边界 dp0,0,0=0,dp0,0,i=1(i>0)

CF1605F PalindORme#

Difficulty : 2900

不知道是怎么想到的。ntf 实在是不平凡的。

你考虑如何判断一个序列是 good 的。设重排后序列 ti 前缀 [1,i] 和后缀 [ni+1,n] 按位或等于 w1[1,i+1][ni,n] 按位或等于 w2。不难发现 w1w2,这说明 w2w1对称差对应的那些位上,ti+1tni 均为 1。于是扔掉顺序,就变成了 bi 里面任取两个数 x,y,令 x,y 为它们去掉当前按位或值 V1 的位的值,那么 x=y,再将 VVor x

合法的序列一定会判断合法,因为每步中满足条件的 x,y,如果它们没有被选,那么接下来选数时 x,y 仍然合法。并且一定可以从一个不合法的序列中拆出一个合法的子序列,而且去掉这个子序列的或和为 1 的位之后,剩下来的数互不相同

为了避免算重,如果剩下的数中有 0,我们将其算进合法子序列内。

然后就可以数数了。设 dpi,j 为长度为 i,按位或的 popcountj不合法序列的方案数。答案枚举 j 求和即可。每次转移就枚举其合法子序列的长度以及值域(因为合法子序列的或值上的 1 可以全部去除),显然:

dpi,j=p[0,i),q[0,j)(gp,qdpp,q)(ip)(jq)2(ip)qfip,jq

其中 gi,j 表示长度 i,值域 [0,2j) 的序列,按位或和为 2j1 的序列个数。fi,j 表示长度 i,值域 [1,2j) 的序列,每个位置上的值互不相同,按位或和为 2j1 的序列个数。gp,qdpp,q 就是合法子序列的个数,然后任取 p 个位置和 q 个二进制位。最后要求 ip 个数要互不相同,而且对于 V1 的位,不合法的部分的数可以任选,所以乘上 2(ip)q

至于如何计算 f,g,容斥一下,钦定一些位为 1,其余任选(f 还是要满足非零且互不相同的条件):

fi,j=jk=0(jk)(1)jk(2k1)i_

gi,j=jk=0(jk)(1)jk(2k)i

做完了,复杂度 O(n2k2)

CF98E Help Shrek and Donkey#

Difficulty : 2700

显然,当双方均有牌的情况下,先手是不可能直接指定桌牌的:正确的概率为 1m+1,错误的概率为 mm+1,显然 mm+11m+1

于是先手指定桌牌的情况只能是 n=0m=0

  • n=0 时,猜测没用(否则后手必胜),直接指定,正确的概率为 1m+1
  • m=0 时,先手直接指定自己没有的那张牌即可,概率为 1

下面讨论 n,m0 的情况。

考虑到先手进行猜测有两种情况:猜测自己有的牌、猜测自己没有的牌。称猜测自己有的牌为“诈骗”,猜测没有的为“询问”,分类讨论:

先手猜测的牌设为 x

  • 若先手诈骗:

后手可以选择认为先手是询问,此时后手没有 x 并且认为先手没有 x,所以他认为桌牌是 x,于是这种情况下先手诈骗成功的概率为 a=1

后手可以选择认为先手是诈骗,此时后手知道先手有 x,等价于先手摊牌 x,下一轮先后手交换,即 b=1f(m,n1)

  • 若先手询问:

那么先手有 mm+1 概率猜中对方的牌,有 1m+1 概率猜到桌牌。

无论后手选择先手是诈骗还是询问,如果猜中了对方的牌,对方都要摊牌,也就是两边的概率都有 mm+1(1f(m1,n))

如果没猜中对方的牌(猜中了桌牌)。如果后手认为先手在询问,那么下一轮他就会直接指定桌牌,此时先手获胜概率为 0;如果后手认为先手在诈骗,后手下一轮就不会指定桌牌,而先手已经知道自己没有的 x 后手也没有,会直接指定,此时先手概率为 1m+1

所以如果此时后手认为先手在询问,先手获胜概率为 c=mm+1(1f(m1,n));否则后手认为先手在诈骗,先手获胜概率为 d=mm+1(1f(m1,n))+1m+1


综合一下,发现先手只要选择了是诈骗还是询问,获胜概率全由后手选择认为先手是诈骗还是询问决定,设先手选择询问的概率为 p

  • 后手认为先手询问,获胜概率 p1=(1p)a+pc=(1p)+mpm+1(1f(m1,n))
  • 后手认为先手诈骗,获胜概率 p2=(1p)b+pd=(1f(m,n1))(1p)+mpm+1(1f(m1,n))+pm+1

根据纳什均衡策略p1=p2,解得 p=(m+1)f(m,n1)(m+1)f(m,n1)+1,于是我们递归求得 p 再带入 p1,p2 中任意一个就可以求出 f(n,m) 了。

AGC034F RNG and XOR#

需要一点数学知识,因为这是集合幂级数优化 dp(?

类似随机游走,令 fi 为第一次操作到 i 的期望操作次数,pi 为每次操作数为 i 个概率,显然有:

fi={0i=01+jxork = ipjfki0

显然可以高斯消元,不过是 O(23n) 的,寄飞。

考虑到转移过程中有类似异或卷积的东西,令 (fp)ijxork =i fjpk,那么 i0 时,(fp)i+1=fi

考虑 (fp)0 的值。由于 ipi=1,于是根据 FWT 的线性性:

i(fp)i=ifii0(fp)i+(fp)0=i0fi+f0(fp)0=f0+2n1

由于 f0=0,那么 (fp)0=2n1,所以用括号表示集合幂级数的话:

(f0f1f2...f2n1)(p0p1p2...p2n1)=(f0+2n1f11f21...f2n11)

接下来就很套路了,由于卷积的每项都带有 fi,那么给 p0 减去 1,相当于给每位减去了 fi,因为 ixor0 = i

(f0f1f2...f2n1)(p01p1p2...p2n1)=(2n111...1)

这是 FP=F 的形式,那么 F=FP1。后面两个都已知,FWT 后点值相除就好了……吗?

注意到 FWT(P)0=FWT(F)0=0FWT(F)0 位你填个啥?

注意到其他位都是对的,那一位可以看作一个变量,肯定有一个数填 c 到这一位使得 IFWT 后是对的。那么我们直接对 (0FWT(F')1FWT(P)1FWT(F')2FWT(P)2...FWT(F')2n1FWT(P)2n1) 做 IFWT,由于第 0 位改变,影响的是每一项,而 IFWT 回去的结果是 f(0) 而不是 f(0)=0,所以给 f 整体减去 f(0) 所得就是答案了。

ARC162F Montage

Difficulty : 3190

手玩一下,容易转化题意为:

按行从上到下填 0/1 矩阵,设第 i非空行上是 1 的位置的集合为 Si,满足:

  • 对于任意 i>1,令 D=SiSi1
  • D=,则 Si 中所有元素均比 Si1 中任意元素小,即 maxiSii<miniSi1i
  • D,则 Si,Si1,D 从小到大排序后,DSi 的后缀,为 Si1 的前缀,即 maxiSiDi<miniDimaxiDi<miniSi1Di

现在这个限制是从右上角走到左下角,那不如先把行翻转一下,就变成了从左上角到右下角:

  • D=miniSii>maxiSi1i
  • DminiSiDi>maxiDiminiDi>maxiSi1Di

那我们直接把空行删掉,令 fi,j,k 表示考虑到第 i 行,第 i 行一共有 j1,最右边的 1 的位置为 k 的方案数。转移枚举新的最右边的 1 的位置 pD 的大小 sSi+1D 的大小 l,转移系数就是个组合数:

fi,j,k(pk1s1)fi+1,l+s,p

枚举非空的行数,答案就是:

ans=1+ni=1(ni)mj=1mj+1k=1fi,j,k

直接做是 O(n6) 的。利用不同的 l 转移相同可用前缀和优化至 O(n5)

然后我们发现把矩阵转置一下,将 n,m 交换不影响答案,也就是说我们可以把空的列也拿出来。于是每个 Si 就是一段区间了,且 Si,Si+1 要么相交不包含要么相邻,Si+1Si 的右边。

fi,j,k 重新定义为 S1=[1,r1],Si=[jk+1,j],满足以上限制的方案数。其实就是把前面的 j,k 两维交换了一下。

那么答案变为:

ans=1+ni=1mj=1(ni)(mj)jk=1fi,j,k

转移还是枚举 Si+1 的两个端点 p,q,满足 jk+1pj+1,max(p,j)qm:

fi,j,kfi+1,q,qp+1

然而这还是 O(n5) 的。由于对于不同的 p 贡献相同,设 fi,j,k 为第三维差分后的 f 数组,可用前缀和优化至 O(n4)

fi,j,kfi+1,q,qmin(j+1,q)+1,fi,j,kfi+1,q,qj+k+1

单独将 q=j 的转移拎出来,这部分 O(n3)

fi,j,kfi+1,j,1,fi,j,kfi+1,j,k+1

剩下的是 qj+1 的转移:

fi,j,kfi+1,q,qj,fi,j,kfi+1,q,qj+k+1

这还是 O(n4) 的,但是我们观察到第二维和第三维的差为定值且与 q 无关,所以令 gi,j,k+1=fi,j,jk

fi,j,kgi+1,q,j+1,fi,j,kgi+1,q,jk

注意到 q[j+1,m],再对 g 的第二维进行差分记作 g,前缀和优化即可做到 O(n3)

fi,j,kgi+1,j+1,j+1,fi,j,kgi+1,j+1,jk

最终时间复杂度 O(n3),空间复杂度 O(n2)

NOMURA Programming Competition 2020 D Urban Planning#

Difficulty : 2810

考虑排列 Pi 已经固定了的情况,那么连边 iPi 形成有向图 G,最小连边数就是 N 减去弱连通块数。善良的出题人已经告诉你连边方案就是 (N1)K,所以答案就是 N(N1)K 减去所有连边方案中弱连通块数量总和。于是只需要考虑所有连边方案中弱连通块数量总和即可。

注意到最后这张图一定是个内向基环树森林,所以某些 Pi 未确定时就应该是个内向基环树加若干内向树构成的森林(孤立点也算内向树)。考虑一个弱连通块 GG,按照其形态分类:

  • G内向基环树,则 G 内的点的 Pi 均固定,且只有一个环,所以对一个连边方案的贡献为 1,算上外部连边方案,总贡献为 (N1)K
  • G内向树,则 G 内存在唯一 Pi 不固定的点 i,就是内向树的。这个连通块有两种选择:
  • Pi 选择 G 内的点,那么 Pi|VG|1 种选择方案(不能选自己),外部还剩 (N1)K1 种方案,那么贡献为 (|VG|1)(N1)K1
  • Pi 选择 G 外的点,那么 G 就变成了某个大内向基环树的子图,而这个基环树除去环边是由若干个内向树组成的。这类贡献有关其它连通块大小,单独拉出来在下面讨论。

刚才的问题可以转化为单独考虑每个大环的贡献,大环是由从 G 中选出若干个形态为内向树的连通块,选出它们的根之后连接组成的。假设选择了 G1,G2,,Gm m 个连通块形成一个环,环上的树的排列方式有圆排列 (m1)! 种,每个根 iPi 可以在下一棵内向树的点中任意选择,选择方案有 |VGi| 种(VG 为构成子图 G 的点集),其余 Pi 未匹配的 iKm 个,选出这些 Pi(N1)Km 种方案。

那么设组成基环树的内向树数量为 m(m2),方案数就是:

(m1)!(N1)KmG1,G2,,Gmmi=1|VGi|

后面这个东西就是个背包,设 f(m)=[xm](|VGi|x+1),可以 O(N2) 背包 dp 求出来,那么 m 的总贡献就是:

(m1)!(N1)Kmf(m)

然后算上之前的贡献就做完了,复杂度 O(N2)。瓶颈在于计算 f(m),可以多项式优化。

数位 dp#

实在没做过啥数位 dp 的题……

CF750G New Year and Binary Tree Paths#

Difficulty : 3200

考虑枚举路径的 LCA 为 x

如果是一条直链,设其长度(点数)为 l,那么一直往左子树走的话,总和就是:

x+2x+4x++2l1x=(2l1)xs

由于 lO(logs) 的,考虑枚举 l,反解出 x

xs2l1

不难发现这同样是 x 的下界。具体地,令 x=x1,考虑从 x 一直往右子树走的路径,此时路径和取到最大,只需证明这个最大值小于 x 为开头的链的最小值(一直往左走)即可:

x+(2x+1)+(2(2x+1)+1)+=(2l1)x+2ll1=(2l1)xl<(2l1)x

所以此时的 x 是固定的。所以枚举 l,算出 x 后自顶向下调整(将某层的左儿子翻转到右儿子)判断是否能取到 s 即可。

类似直链的情况,拓展到分叉上:枚举以左儿子为开头向下的链长度(点数)为 l1,右儿子为 l2。这条路径的总和为:

f(x,l1,l2)=x+(2l11)2x+(2l21)(2x+1)=(2l1+1+2l2+13)x+2l21s

xs2l2+12l1+1+2l2+13

同样可以发现这里的 x 是固定的,解出 x 后令 r=sf(x)。考虑翻转链上一个左儿子产生的贡献,等价于下列问题:

给定 2 个集合 {211,221,,2l11}{211,221,,2l21},从中选择若干元素,使得总和为 r,求方案数。

这东西显然很不好做,考虑转成 2 的幂,枚举选出来元素的个数 n,相当于从 {21,22,,2l1}{21,22,,2l2} 中选择 n 个元素,和为 r+n。这里的集合为可重集。

显然 2(r+n) 时无解,否则整体除 2 后数位 dp。令 fi,j,0/1 表示从小到大考虑到 t=r+n2 的第 i 位,选了 j 个数,当前位是否有进位的方案数。答案就是 flogt,n,0,转移的话考虑两边同时取/取一个/都不取分类讨论一下即可。

复杂度 O(log5s)

dp 套 dp#

SDOI2022 小 N 的独立集#

dp 套 dp 的含义就是用外层 dp 的状态表示内层 dp 的结果

考虑普通的树形 dp 求最大权独立集,fu,0/1 表示 u 的子树中 u 是否选择的最大权独立集大小,转移显然。

那么一个朴素的想法就是令 gu,x,y 表示 fu,0=xfu,1=y 的方案数。每次枚举并加入儿子 v 的贡献:

gu,x+max(z,w),y+zgu,x,ygv,z,w

然而这样状态数是 O(n3k2) 的,根据树形背包知道这个做法是 O(n4k4) 的。考虑优化。

考虑修改状态,令 fu,0/1u 子树是否强制不选择 u 的最大权独立集大小。转移是显然的。

注意到 0fu,0fu,1auk,分类讨论即可。

那么可以设 gu,x,y 表示 fu,1xfu,0fu,1y 的方案数,显然有状态数 O(n2k2),再做树形背包就是 O(n2k4) 的了。转移推一下即可。

数据结构优化#

CF115E Linear Kingdom Races#

Difficulty : 2400

fi 表示考虑前 i 条道路的最大收益。

如果不修复这条道路,fi=fi1

如果修复,fi=max0j<i{fjc(j+1,i)+p(j+1,i)},即将 [j+1,i] 全部覆盖。

然后这个 dp 大概是 O(n2) 的,用脑子线段树在线维护跑到某个 i 时每个 jfjc(j+1,i)+p(j+1,i) 即可 O(nlogn)

ZJOI2010 基站选址#

常规套路,设 dpi,j 表示在第 i 个村庄建立第 j 个基站,不考虑 i+1n 对答案贡献的最小费用。转移显然有:

dpi,j=min1ki1{dpk,j1+costk,i}+ci

其中 costk,i 表示如果ij 两个位置建站,它们之间村庄需要的总补偿。为了方便,我们从 1i1 枚举 k,并把 dpi,j(i<j) 的值赋为 inf

暴力做是 O(n2k) 的,考虑用数据结构优化。

这个状态的第二维肯定不能扔,考虑在最外层枚举 j,那么状态转移变为:

dpi=min1k<i{dpk+costk,i}+ci

我们想用线段树动态维护对于每一个 kdpk+costk,i 的值,那么转移就变成了区间取 min

i1i 移动时,有一些 costk,i 会增加,我们考虑统计它们。我们考虑对所有的 i,计算出在 k 点建站使其被覆盖的最大和最小的 k,记为 li,ri,并在 i 移动时,考虑计算每个 rj=i1kcost 的贡献,显然对于一个 rj=i1j,它会使得 cost1,icostlj1,i 上的值全部加上 wj。因为在这个区间内建站都不会覆盖到它,并且 i 也不会覆盖到它。

于是我们的线段树只需要维护区间加法,区间取最小值即可。复杂度 O(knlogn)

CF1175G Yet Another Partiton Problem#

Difficulty : 3000

应该是一个很通用的解法。

一个显然的分段 dp:

fj,i 表示前 i 个数分 j 段的方案数,fj,ii1mink=0fj1,k+w(k+1,i)

可以滚动数组,fii1mink=0gk+w(k+1,i)。这是好理解的。

考虑到分段 dp 的价值函数大多数满足决策单调性,然后就发现 w(k+1,i)=(ik)imaxr=k+1ar 不满足决策单调性,很好,寄。

考虑 [1,i] 这个前缀中每个下标 j,求出 vj=imink=j+1ak,那么 v 显然能够分成若干个连续段,每段 v 值相等。并且 ii+1 时,这个连续段是好维护的,使用单调栈即可。注意到这个维护顺序和 dp 顺序一样,这也非常好。

考虑一个连续段 d=vl=vl+1=vl+2==vr,对于 j[l,r]w(j+1,i)=(ij)d,所以对于这个段我们只需要找到 minljrgj+d(ij)=minljrgj+didj=di+minljrgjdj。于是对点集 {(j,gj)j[l,r]} 维护一个下凸壳,每次拿斜率为 d 的直线切这个凸包即可,我们给连续段标号(实际实现可以直接用右端点编号),并求出第 l 个连续段的切点为 (pl,gpl)

那么我们需要对于所有连续段 l,求出 minlgpl+(il)vpl,我去,这太典了,这是个关于 i 的一次函数,直接用李超线段树维护即可。具体来说,当 ii+1 时,可能会合并一些连续段,假如合并的是 x,y 连续段,那么我们将 x,y 里面两个下凸壳合并起来(注意使用启发式合并),取最优的 (pl,gpl) 决策点,将 y=gpllvpl+vpli 加入李超线段树,并删去原本 x,y 两个下凸壳里面的决策点。

由于要实现删除,所以要用可持久化李超树/可撤销李超线段树。可持久化的话,每个连续段标号为右端点下标,直接从单调栈的栈顶(往前找第一个大于 ai 的位置)的版本继承过来就可以了。

复杂度 O(knlogn)

CF1530H Turing's Award#

Difficulty : 3400

你发现这个覆盖不太好考虑,考虑时间倒流,变成如下形式:

一开始,小 A 的位置上有一个数 an,然后对于接下来 n1 步,每次小 A 可以向左走/向右走/不动,然后如果此时小 A 所站的位置上没有数,就写上 ai,求最后形成序列的最长上升子序列长度。

考虑到任意时刻的序列一定是包含原点的连续序列 b,并且此时不能覆盖有数的位置,那么 ai 只可能插入到 b 的首尾两个位置。

我们将所有最终b 中的元素 ai 成为「好」的元素,显然 an 一定是好元素,观察到:

  1. 我们并不关心小 A 走到 b 中间哪个位置,只关心他是否有时间在已经确定的连续好元素之间移动。例如,目前考虑了 ai,ai+1,,an,钦定 ai 为好元素并且插入到 b首位(插入末尾的情况是对称的),目前 ai,ai+1,,an 中一共有 k 个好元素,考虑第 k+1 个好元素 aj(j<i)
  • 如果 aj 插入在 b首位,我们可以在小 A 走过 i1,i2,,j+1 的时候都选择留在原位,这样保证不会覆盖,然后 j 时刻再向左移动一位。所以这种情况没有限制。
  • 如果 aj 插入在 b末尾,小 A 要走过 k 个好元素。那么需要满足 ijk
  1. 考虑一个好元素 ajjn)如果存在一种方案使得 aj 在最终的 b 序列里不在 LIS 中,一定存在一种方案使得 aj 最终不在 b 序列中,因为可以在时刻 j 留在原地不动。所以我们更改好元素的定义:最终出现在 LIS 中的元素(包括 an)。

然后我们可以讨论 an 是否属于 LIS,考虑 dp:

fL(k,i) 表示当前从 n 考虑到 iai 插入到了 LIS 的首位,目前一共有 k 个好元素,LIS 末尾元素的最小值fR(k,i) 表示当前从 n 考虑到 iai 插入到了 LIS 的末尾,目前一共有 k 个好元素,LIS 首位元素的最大值。那么我们要求的就是最大的 k,使得存在一个 i,状态 fL(k,i) 或者 fR(k,i) 合法(属于 [1,n])。

根据 an 是否属于 LIS,我们可以确定 dp 的初始状态。

考虑 fL(k,i) 可以贡献到的状态(fR(k,i) 类似),讨论新的好元素 aj 放左还是放右即可:

  • fL(k,i)fL(k+1,j)j<iaj<ai
  • aifR(k+1,j) j<ikaj>fL(k,i)

那么不难得到 fL(k,i),fR(k,i) 的转移:

fL(k+1,i)=min(minj>iaj>aifL(k,j),minji+kfR(k,j)aiaj)fR(k+1,i)=max(maxj>iaj<aifR(k,j),maxji+kfL(k,j)aiaj)

显然可以优化,用两个数据结构支持查询前缀 max 和后缀 min 即可。复杂度 O(knlogn)k 为答案,考虑到均匀随机序列的 LIS 长度期望为 O(n)kO(n),复杂度 O(nnlogn)

其实这里有一个简易的 dp 优化套路:将 dp 答案与状态的一维交换,例如我们也可以按照 LIS 的首尾位为状态 dp,但是复杂度更劣。所以把 LIS 长度列入 dp 状态。

斜率 | 单调队列 | 决策单调性 | 凸完全单调性优化#

CF311B Cats Transport#

Difficulty : 2400

dp 斜率优化板子。

对于每只猫,算出最晚的能够 pick 它的出发时间 ti,这个可以用前缀和做。

然后我们将 t 序列从小到大排序,我们发现一个人 pick 到的猫在这个序列上一定是一段连续的区间。

然后问题就转换成了给定一个序列 t,将其分成 p 段,使得 krki=lktrkti 最小。

fi,j 表示分成 i 段,末尾为 j 的最小答案。设 si=ik=1tk,则不难得出转移:

fi,j=j1mink=0(fi1,k+tj(jk)sj+sk)

于是第 i1 行的 f 值会影响到第 i 行的值,考虑开 p 个单调队列来优化 dp。

为了题解简洁,以下把第一位省略。

转移的式子为 fi=tij+sj+fjsi+iti

整理一下:fi+siiti=ti×j+(sj+fj)

然后这就是标准的斜率优化形式了,复杂度 O(mp)

CF868F Yet Another Minimization Problem & CF1527E Partition Game#

Difficulty : 2500

记两道决策单调性优化 dp 板子。

对于前一道,dpi,j 表示前 j 个数分 i 段的最小答案,dpi,jdpi1.k+w(k+1,j)

首先显然这个满足决策单调性,然后就可以分治 dp 了。

第二道差不多一样,移动指针麻烦一点。

CF321E Ciel and Gondolas#

决策单调性的另一个结论。

w(l,r)[l,r] 之间的两两和,fi,jjmink=1{fi1,k1+w(k,j)}

显然的决策单调性,分治可以做到 O(nklogn),除去 O(nlognlogk) 的 wqs 二分不谈,其实可以 O(n2)

一个满足四边形不等式的状态,记录 op(i,j)(i,j) 的最优决策点。则:

op(l,r1)op(l,r)op(l+1,r)

然后记录每个状态的转移区间,直接 dp 即可。

正确性及复杂度证明可见 OI Wiki

CF1699E Three Days Grace#

Difficulty : 2600

不知道算不算双指针优化。

考虑最终答案方案的值域。

如果固定值域左端点为 i,此时最小答案应是 max{fak}ifk 表示将 k 拆分成若干个不小于 i 的数后得到的最大因数的最小值。

于是考虑在 im1 的过程中,转移 fk

首先如果 ik,显然 fk=fkf 表示从 i+1 转移 i 后的 f 数组)。

如果 ik,考虑拆出一个 i 的条件是 kii,即 ki2 时,fkfki

注意到被转移的都是 i 的倍数,于是如果枚举每次转移的位置,就可以做到调和级数转移了。

还有一个问题,如何统计答案。也就是对于每一个 i,求出 max{fak}

我们发现转移时是取 min 的,也就是说 f 的最大值单调不增。

用另外一个指针 j,表示 max{fak} 即可。由于 j 随着 i 的下降而不增,移动 j 的复杂度是 O(m) 的。

总复杂度 O(mlogm)

CF1603D Artistic Partition#

Difficulty : 3000

首先如果 2k>n,答案为 n

否则 klog2n,然后就可以令 dpi,j 表示前 i 个数分 j 段的最小答案。

dpi,j=imink=1{dpk1,j1+c(k,i)}

考虑到:

c(l,r)=ri=lrj=l[gcd(i,j)l]=rk=lri=lrj=i[gcd(i,j)=k]=rk=lr/ki=1φ(i)=rk=lSφ(rk)

我们发现它有决策单调性!

于是可以 O(nn) 预处理 vali,j 表示 r=i 并且 nk=jrk=lSφ(rk) 的值(此时 l 为满足 nl=nr 最小的 l)。

然后 c(l,r)=r/l1k=1valr,i+Sφ(rl)(rl+1)r 为使 rr=rl 最大的 r,可以 O(1) 求出。

于是可以在 O(nn+nlog2n) 的复杂度内解决此题。

但我觉得预处理太麻烦了咋办?

我们发现,在移动区间左端点时,每向左移 1 位就对转移答案贡献 Sφ(rl),而总移动次数不超过 O(nlogn) 次,我们可以在开始就暴力 O(n) 算出 c(pr+1,mid) 的值,然后 l 指针从 pr 移到 pl(可转移的区间)的过程中加贡献即可。

由于对于每个 mid 仅算了一次 c(pr+1,mid),于是这部分应该是 O(nnlogn) 的,整个 dp 过程应该是 O(nnlogn+nlog2n) 的,但是不知道为啥能过(可能是因为每次计算 c(pr+1,mid) 区间长度远远达不到 n),如果有会证明时间复杂度的好哥哥可以打我(

ARC125F Tree Degree Subset Sum#

Difficulty : 3500

pb 讲课题。

显然树的具体形态对题目影响不大,那么我们知道 ni=1di=2n2 即可扔掉树的条件。即:

给定 ndi,和为 2n2,求 (x,y) 满足 0xnS{1,2,n},|S|=x,iSdi=y 的数量。

我们考虑如何解决这个问题。首先可以将所有 di 减去 1,那么 ni=1di=n2。然后我们考虑证明,对于任意的 y,设 m(y)M(y)最小和最大的 x 使得 (x,y) 合法,那么有 i[m(y),M(y)](i,y) 合法:

  • x(S)=|S|,y(S)=iSdi
  • 我们设 di=0i 的个数为 z,由于 m(y) 的方案中没有选 di=0M(y) 的方案中一定选了 zdi=0,所以只需要证明 M(y)m(y)2z+1 即可通过调整 0 的个数构造出 x[m(y),M(y)]
  • 由于对于每个集合 S{1,2,n}zy(S)x(S)z2(左边全取 0,右边全取非 0),所以对于任意的 yzyM(y)ym(y)z2
  • 解不等式即可得到 M(y)m(y)2z2<2z+1

考虑得到了 i[m(y),M(y)](i,y) 合法这个结论,如何求出方案数。由于 yn2,考虑处理出对于每个 yM(y)m(y) 的值,然后对 M(y)m(y)+1 求和就是答案。

注意到 d 的总和为 n2,显然 di 中非 0 的互不相同的数至多只有 O(n) 个,不难想到用单调队列优化多重背包。具体地,以 M(y) 为例,设 ci=nj=1[dj=i]fi,j 表示考虑了 1i 中的所有 dk=i,当前 y(S)j 的方案数。那么:

fi,jcimaxk=0(fi1,jki+k)

套路地将 j 拆成 xi+y,且 0y<i,设 gy,x=fi,xi+ygy,x=fi1,xi+y

gy,x=cimaxk=0(gy,xk+k)=cimaxk=0(gy,xk(xk))+x

这就是经典的单调队列优化的形式了。考虑外层枚举 yi,内层 xni,物品数量为 O(n),总复杂度是 nn 的。

最后统计答案需要将 di=0 的贡献算上。

Luogu8544 「Wdoi-2」禁断之门对面,是此世还是彼世#

Part 1. 转换#

由于 Ai,j=aibj,这个 f(B) 显然可以化简:

f(B)=ni=1tj=1max(Bi,j,Bi+1,j)k=min(Bi,j,Bi+1,j)Ai,k=ni=1tj=1max(Bi,j,Bi+1,j)k=min(Bi,j,Bi+1,j)aibk=ni=1aitj=1Smax(Bi,j,Bi+1,j)Smin(Bi,j,Bi+1,j)1

Sib 数组的前缀和。

发现若得到 g(B1,B2)=tj=1Smax(B1,j,B2,j)Smin(B1,j,B2,j)1 的最小值,我们可以令 B2k+1=B1,B2k+2=B2。这样显然最优。也就是说,f(B)=(ni=1ai)ming(B1,B2)

问题转换为找到一个 B1,B2,分别满足每个元素两两不同,都在 [1,m] 之间,并且对应的位置上的元素不同,使得 g(B1,B2) 最小。

由于同一行元素两两不同以及值域的限制,考虑转换成匹配问题。相当于现在有两列数(分为左部和右部),分别为 1,2,,m,在左部中选择 t 个数,并和右部的 t 个数匹配。满足不存在形如 (i,i) 的匹配,一对匹配 (i,j) 的价值就是 Smax(i,j)Smin(i,j)1,也就是 bmin(i,j)+bmin(i,j)+1++bmax(i,j)。一组匹配的价值就是每对匹配的价值之和,求钦定有 t 对匹配的最小匹配

Part 2. 猜想#

有个比较感性的想法,就是一对匹配不应该跨过太大的距离。考虑从左到右按顺序匹配,如果匹配跨过了一段空区间,那么不如不跨过这段区间,因为这样减小了代价的同时也给后面的点更多的选择方案。

另一个比较感性的想法,匹配应该尽可能不交叉。这里借用这篇题解的图:

如上图,匹配 (2,5)(4,3) 显然不如匹配 (2,3),(4,5)。即如果存在交叉的匹配,我们尝试交换匹配以减少价值。而且可以发现减少交叉必定不劣。

手玩一些数据之后,我们发现最优解中,i 只能形成 (i,j)(j{i2,i1,i+1,i+2}) 的匹配。我们下面试图证明这个结论。

Part 3. 证明#

i 显然可以和 i1,i+1 匹配,即证最优解中合法匹配 (i,j) 满足 ji2。下面从左到右考虑一组匹配 (i,j)(j>i+2) 如何调整(小于 i 的左部点的匹配均满足猜想),j<i2 根据对称性同理:

  • k{1,2},不存在匹配 (?,i+k)(即右部的 i+k 没有被匹配),显然将 (i,j) 调整为 (i,i+k) 更优。
  • 否则存在 (x,i+1),(y,i+2) 的匹配,且我们从左到右调整,显然有 x,y>ixy。注意到匹配 (i,j)(x,i+1),(y,i+2) 都有上述的交叉,所以我们试图交换两个匹配的右部点以减少交叉:若 x=j,则 yj,将原匹配 (i,j)(y,i+2) 重组为 (i,i+2)(y,j) 即可;若 xj,将原匹配 (i,j)(x,i+1) 重组为 (i,i+1)(x,j) 即可。

这样我们就能够将任意的合法匹配调整为更优的、满足 i 只能形成 (i,j)(j{i2,i1,i+1,i+2}) 的匹配的方案。

最终只剩下三种结构:连续的三元环,例如 (i,i+1)(i+1,i+2)(i+2,i) ;连续的二元环,例如 (i,i+1)(i+1,i);连续的一条链,例如 (i,i+1)(i+1,i+2)(i+2,i+3)(i+k,i+k+1)。前两种情况有交叉,但是无法调整;并且能够发现,只有前两种情况无法调整。

Part 4. 你会了#

然后就能考虑 dp 了:令 fi,j,0/1 表示目前考虑到 i 的匹配 (i,?),前 i 个点一共有 j 对匹配,目前是否在一条形如 (u,u+1)(u+1,u+2)(i1,i) 的链中。

  • fi,j,1fi1,j1,1+bi+bi1,表示延续一条链,增加一对匹配,连接 (i1,i)
  • fi,j,1fi2,j1,0+bi+bi1,表示新建一条链,增加一对匹配,连接 (i1,i)
  • fi,j,0fi2,j2,0+2(bi+bi1),表示新增一个二元环,增加两对匹配,连接 (i1,i)(i,i1)
  • fi,j,0fi3,j3,0+2bi+3bi1+2bi2,表示新增一个三元环,增加三对匹配,连接 (i2,i1)(i1,i)(i,i2) 或者 (i,i1)(i1,i2),(i2,i)
  • fi,j,0fi1,j,0,表示 i 没有匹配任何点。
  • fi,j,0fi,j,1,表示我摆烂了,不延续一条链。

乍一看是 O(mt) 的?的确是 O(mt) 的。

考虑瓶颈在于强制选择 t 对匹配,对于这类问题,我们可以通过证明答案随匹配数的变化具有凸性,而进行 wqs 二分。

这题的凸性十分显然,因为是匹配问题,可以转化成费用流模型:

  • 有超源 S 和超汇 T,源点 S 和汇点 TSS 连流量 t,费用 0 的边(以下 uv 连流量 f 费用 w 的边简记为 uv(f,w))。即 SS(t,0),TT(t,0)
  • i 的左部点为 li,右部点为 riSli(1,0),riT(1,0)
  • 对于 ijliri(1,Smax(i,j)Smin(i,j)1)

不难发现最小费用最大流就是答案。根据费用流函数的凸性,原问题具有凸性,可以 wqs 二分。具体地,二分斜率 k,新建一对匹配时,直接减去 k 的代价即可。

最终复杂度 O(nlogV)。代码好写得很。

矩阵加速优化#

CF852B Neural Network country#

Difficulty : 2000

dp 与矩阵快速幂优化。

考虑 dp,因为层与层之间的转移过程相同,可以快速幂。

dpi,j 表示第 i 层长度 modmj 的方案数。

那么 dpi,jdpi1,jck,ck=ni=1[vi=k]

然后你发现这是一个类似卷积的形式,快速幂优化即可。

写了很久,后面看题解才发现要把汇点和最后一层合并,不然会出错。

CF1152F2 Neko Rules the Catniverse (Large Version)#

Difficulty : 3000

发现挨位考虑填哪个不太现实,考虑值域。

dpi,j,st 表示考虑到 i,此时序列长度为 jimi1 填空状态为 st 的方案数,考虑选/不选数即可:

dpi,j,st×(popcount(st)+1)dpi+1,j+1,(2st+1)&2m,dpi+1,j,(2st)&2m

乘上那个 popcount(st)+1 是因为 i 只能放到 ak=[im,i1] 位置 k 的后面或者开头。

然后发现 O(n2mk) 不太行,但是 2m×k 非常小,想到矩阵优化。

复杂度 O((2mk)3logn) 即可。

CF755G PolandBall and Many Other Balls #

Difficulty : 3200

列出转移方程就是傻鸟题了,具体地,令 fi,j 为前 i 球取出 j 组的方案数,有:

fi,j=fi1,j1+fi1,j+fi2,j1

列出 fi 的 GF Fi(x)

Fi(x)=Fi1(1+x)+Fi2x

这是递推,把矩阵元素改成多项式,矩阵快速幂即可。O(klogklogn)

多项式优化#

CF995F Cowmpany Cowmpensation#

Difficulty : 2700

考虑一个 dp 的推。设 fu,i 表示 u 子树中填 [1,i] 符合题目条件的方案数,此时不强制 ui,所以有:

fu,i=fu,i1+vson(u)fv,i

直接做是 O(nd) 的。考虑奇技淫巧优化。

考虑到边界情况,就是 u 为叶子时,fu,i=i,这是个关于 i一次函数

同时这个转移形式比较诡异,是儿子的值全部乘积然后求和。那么如果设 ufu,i 是关于 igu 次函数的话,对于树上任意一个非叶节点:

gu=deg(vson(u)fv,i)=vson(u)gv

由于 v 是叶子时 gv=1,我们容易归纳出 gu=szu,即 u子树大小。于是 fu,i 是关于 iszu 次函数。

如果 dn+1,直接暴力 dp;否则处理出 fn,1fn,n+1 的值,用拉格朗日插值把 fn,d 插出来即可。

复杂度 O(n2)

AGC020F Arcs on a Circle#

Difficulty : Unavailable

先考虑只能放整点的情况,不难想到考虑 dp。

对于环上的 dp,考虑断环成链,即钦定一条线段的左端点为起点。这里我们令长度最长的线段的左端点为环的起点。

这样做有一个好处:我们不用考虑一条线段把环末尾覆盖再覆盖开头的空的情况,而当我们钦定一个长度较小的线段作为起点时,在环的末尾放一个长度较长的线段有可能覆盖到环开头的空隙中,这样是合法的,但判不到。

然后就相当于固定了一个前缀被覆盖,剩下 n1 条线段,由于 n 的范围较小,不难想到状压。同时我们考虑从前往后枚举线段起点,这样任意时刻覆盖的都是一段前缀。具体来讲,我们设 fi,S 表示覆盖了 [0,i] 这段极长前缀,用了 S 集合中线段的方案数(最长线段,即我们已经钦定位置的线段不算)。

转移时枚举线段起点 i、要填的线段 j、上一刻 S 集合的状态 T 以及上一刻覆盖到的前缀 [0,w] 即可。由于我们钦定了最长线段为起点,中途我们一旦留下了空隙以后就无法弥补了,所以 wi。我们用 wi+lj 去更新现在的极长前缀,那么有:

fmin(c,max(w,i+lj)),T{j}fw,T

然后这是只能放整点的情况,现在考虑任意实点的情况。

考虑刚才的 dp 时间复杂度 O(c2n2n),发现这个时间限制相当富余,我们考虑乱搞。

具体来讲,我们将圆和弧细分成 m 段,满足 cm。我们再给 lic 乘上 mc,做刚才的 dp。显然,当 m 越大时,可以取的整点就越多。当 m+ 时,我们可以认为圆环上所有实点都可以取到。

于是我们又有一个 O(m2n2n) 的 dp 了,其中 m+。考虑优化复杂度。

我们想起一种 dp 优化方法,在值域很大,另一维很小,答案满足为关于值域的较小次数多项式时,可以用拉格朗日插值优化。例如这题

类似地,这题我们放大眼睛观察,我们发现任意摆放线段时,合法的方案数是一个关于 mn 次多项式。当我们钦定最长线段起点时,方案数就是一个关于 mn1 次多项式但我不会证。感性理解一下,每次插入一条线段最多使次数增加 1,而一共 n1 条线段,所以多项式次数不超过 n1

于是我们取 m=c,2c,,nc 即可得到这个多项式的 n 个点值,而我们要求:

limm+f(m)mn1

上面是合法的方案数,下面是总方案数,除一下就是概率。同时不难发现这东西就是 [mn1]f(m),即求最高次数项的系数

回忆拉格朗日插值公式:

f(x)=ni=1yijixxjxixj

相当于若干个一次式相乘,每个一次式里面取一次项或常数项。但是由于我们要求最高次数项,我们只能取一次项,所以:

[xn1]f(x)=ni=1yiji1xixj

代入 yi=fic,U 就做完了。复杂度 O(c2n42n),其实由于钦定的最长线段,应该是 2n1,所以常数很小。

ABC331G Collect Them All#

Difficulty : 2668

对于一个随机过程,令 ti 为拿到第 i 个数的时间。那么答案就是 E(maxti)

板板 min-max 容斥:

E(maxti)=T(1)|T|+1E(miniTti)=T(1)|T|+1niTci

有一个经典的背包 dp,令 fi,j 表示选到 iT 集合元素之和为 j,所有方案的 (1)|T|+1 的和,那么 fi,j=fi1,jfi1,jci,答案就是 nni=0fm,ii

写成生成函数的形式,也就是 F(x)=mi=1(1xci)

然后就是套路了,分治 NTT 或者 exp 后求逆均可。

状态设计优化#

CF1188D Make Equal#

Difficulty : 3100

有一个简单的想法,就是把所有数都加到最大值上面。

但是这个想法显然是错的,观察样例 2 知道你可以改变最大值以缩小答案。

考虑最大值被加了多少,记为 x,即求 minx{ni=1popcount(x+a1ai)},此处假设 a 从大到小排序。

aia1ai,则即求 minx{ni=1popcount(x+ai)}

考虑从低到高填 xx+ai 的第 k 位由 3 个因素决定:

  • x 的第 k
  • ai 的第 k
  • x+ai 前一位是否进位

前两个一个是决策一个是确定的,考虑将第 3 个因素加入 dp 状态。

然后你考虑对于每个 i[1,n] 记录进位/不进位,得到了一个状态 O(2n) 的做法,您死了

然后你发现一个性质:进位的数一定都是 aimod2k 尽量大的数,也就是说按照 ai 的第 k1 位从大到小排序后,可以取来进位的一定是一段前缀(在这里我们不关心 k1 位为 0/1 的数之间的大小关系,而只关心 k1 位进位的个数),我们可以枚举这个在第 k1 位的前缀。

cnt 为第 k 位为 1 的数的总个数,tot 表示当前前缀第 k 位为 1 的数的个数。

  • 如果 i 在前缀中(意味着计算 k1 位时它对第 k 位有进位)且这一位为 1,这样的数共有 tot 个。
  • k1 位进位(等价于在前缀中),且这一位为 0 的数有 lentot 个,len 位当前枚举的前缀长度。
  • k1 位不进位,且这一位为 1 的数有 cnttot 个(总共第 k 位为 1 的有 cnt 个,在前缀中的有 tot 个,于是不在前缀中的就是 cnttot 个了)。
  • k1 位不进位,且这一位位 0 的数有 nlencnt+tot 个(第 k1 不进位,即不再前缀中的数有 nlen 个,减去不在前缀中且这一位为 1 的即可)。

然后就可以考虑决策:

  • 如果 xk 位填 1:第 1,2,3 种情况对第 k+1 位有贡献,共 tot+(lentot)+(cnttot)=len+cnttot 个进位;第 k 位为 1 的为情况 1,4,于是 kk+1 有贡献 tot+(nlencnt+tot)=nlencnt
  • 如果 xk 位填 0:第 1 种情况有进位,为 tot 次;情况 2,3k 为会有 1,贡献 (lentot)+(cnttot)=len+cnt2×tot

dpi,j 为考虑到第 i 位,第 i1 位有 j 次进位的最小答案(也就是前缀长度为 j),依照上面 O(nlogw) dp 即可。

AGC043C Giant Graph#

我不知道这算不算 dp 优化。

由于 1018 远大于 n,我们可以贪心地选择 x+y+z 尽量大的点。于是我们将 x+y+zx+y+z(x,y,z)(x,y,z)有向边

考虑一个 dp,令 fx,y,z 表示是否选择 (x,y,z) 这个点,是则为 1,否则为 0

显然有 fx,y,z=(x,y,z)(x,y,z)[fx,y,z=0],即如果一个点的后继都不被选,我们就可以贪心地选择这个点;如果一个点地后继中有被选的,那这个点就不能被选。

这东西显然就是个博弈图。fx,y,z0 就是必胜态,1 为必败态。于是我们需要选择所有处于必败态的点的权值。

容易发现,这就相当于在三个图上,分别有一个点,为 x,y,z,每次选择 x,y,z 中的一个沿着有向边移动,不能移动的人输。三个图的 SG 值异或起来为 0 的话在原图上就是必败态了。

由于 DAGSG 值不超过 O(n),可以 O(n) 枚举两个图的 SGi,j,另一个图取 SG 值为 ij 的点即可。

posted @   Arghariza  阅读(159)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示
主题色彩