模拟赛8.8 解题报告

T1 只因数分解

题意:给出 Tn,m,对于每组 n,m 你都需要找出一种把 m 分成不超过 n 个数的方案,每个数都是 n! 约数。1T2×105, 1n20, 1mn!

这个东西居然被我乱搞搞过去了……考场做法是每次找一个 s,枚举 i=n...1s×im 时就令 ss×i,然后 mms

理论复杂度为 O(Tn2),会超时,然后……其他人用这个全 T,由于我的代码过短 A 了……。

官方正解是 O(Tn) 的:考虑阶乘进位制,即考虑拆解 m=i=1ni!ai,,其中 aii,那么每一位处理一次就行。

但有可能存在 ai=i 的情况,此时 i!ai 不一定是 n! 的约数。考虑把位权反过来,即第 i 位的位权从 i! 变为 n(n1)(n2)...(ni+1),此时有 ai<ni,即可解决。

这种方法也间接证明了我的乱搞是正确的。

T2 宇宙射线

搬题链接:P9378 物理实验

题意:一共有 n 个实验,你每次可以任意选择一个还没做并且没有被破坏的实验来做实验。有 m 轮宇宙射线,第 i 轮在做完 ai 个实验后出现,并且有一个 1...n 排列 Pi,j。第 i 轮宇宙射线会破坏第 Pi,j 个实验,满足:

  • 实验 Pi,1...j1 要么做过,要么被破坏过

  • 实验 Pi,j 没做过也没破坏过

显然你可以做 nm 个实验。做第 i 个实验的收益为 2ni,求一种做实验顺序方案使得总收益最大。1n600, 1mn12, 1a1<a2<...<am<nm

经典套路,枚举 i=1...n,当前能选第 i 个实验就选,因为如果不选,后面实验全做的收益也没有 i 多。

问题变成判断一个做的实验集合 S 是否合法。枚举每个射线,然后维护 k 表示当前至少需要做 kS 中的实验。

时间复杂度 O(n2m)

T3 崩原之战Ⅱ

题意:有 n 个区间,第 i 个区间 [li,ri] 的种类为 ci(ci{0,1}),选择若干个区间,使得种类不同的区间无交集,求选择方案数。1n105

实用价值高!但就是原题面漏洞百出……

先把所有区间从小到大排序。

f[i] 表示考虑了区间 1...i 且区间 i 必须选择的方案数。

不能在包含关系之间转移,这样会使得转移条件混乱。考虑第 i 个区间和前面选择的几个同种类的区间构成的 同种类区间连续段。为了构建这个结构,求出 pi 表示满足 rj<li 的最大的 j,枚举选择的上一个不同种类的区间 j(j<i,rj<li),用 j=0 表示不存在这样的区间,转移:

f[i]=j=0pif[j]×[cj=1ci]×2g[i1,j,ci]

其中 g[i,j,c] 表示前 i 个区间中,lk>rjck=c 的区间 k 的个数,在转移方程中的意义为 j 之后 i 之前的与 i 同种类区间任意选。

h[i,j,c] 表示 f[j]×[cj=1c]×2g[i1,j,c]

那么

f[i]=j=0pih[i,j,c]

注意到 g[i,j,c] 容易转移:

{g[i,j,c]=g[i1,j,c]+1jpi,c=cig[i,j,c]=g[i1,j,c]otherwise

放到 h[i,j,c] 有:

{h[i,j,c]=h[i1,j,c]×2jpi,c=cih[i,j,c]=h[i1,j,c]otherwise

i 看做常量,我们对于 h 开两棵线段树,保存 h[i,0...n,0],h[i,0...n,1]

于是我们只需要对线段树

  • 前缀 ×2
  • 求前缀和
  • 单点加

时间复杂度 O(nlogn)

T4 跳水运动员

题意:给出一棵 n 个点的树,把 1...n 分若干段,每一段映射在树上是一个连通块,求分别分成 1,2,3,...,m 段的方案数。1n2×105, 1mmin(n,400)

subtask4 对我们有很大启示,先思考如何做 subtask4,即 fai<i 的情况。

一个段合法,当且仅当这个段至多有一个 x 满足 fax 不处于段内,想象一下放在树上,正确性显然。

f[k,i] 表示把 1...ik 段的方案数。DP 时,如果我们枚举 j 计算 f[k][i]f[k,i]+f[k1,j],那么很难这个段是否合法。考虑倒着做,设 f[k,i] 表示把 i...nk 段的方案数,枚举 j,那么 i...j 中至多一个点的父亲 <i(在 subtask4 中,这样的点显然只有 i)。找出最小的 x 满足 xi,fax<i,最小的 y 满足 y>x,yi,fay<i,那么决策 j[x+1,y]。如何查找?我们可以用一个 set,扫到 i 时把 i 加入集合,在 fai 的位置挂上删除 i 的标记。

进一步思考如何做 subtask5。当 fai 可以小于 i 也可以大于 i 时,我们仍然正着枚举,设 f[k,i] 表示把 1...ik 段的方案数。对于 <i,fa>i 的点,我们仍然像 subtask4 的做法,找出最大的 x 满足 xi,fax>i、最大的 y 满足 y<x,yi,fay>i。对于 j[y,x1],段 [j+1,i] 存在点 x 满足 fax 不在 [j+1,i] 内,那么这个段内就不能有父亲 j 的点。

i 看做常量,维护 cj 表示 [j+1,i] 内有多少个点的父亲 j,显然我们只关注 cj<2j。当 j[y,x1] 时,不能有 faj 的点,即统计有多少个 j 满足 j[y,x1],cj=0;当 j[x,i1] 时,允许有至多 1 个点 faj,即统计有多少个 j 满足 j[x,i1],cj=0/1

维护集合 st0 表示 cj=0j 集合,st1 表示 cj=1j 集合。当遇到一个 fai<i 的点,对于 j[fai,i1]cjcj+1,即把 st1[fai,i1] 的数删除,把 st0[fai,i1] 的数移到 st1

每个数至多添加一次、移动一次、删除一次,因此集合操作均摊复杂度正确。每次查找一个 [fai,i1] 的数为 O(logn),总时间复杂度 O(nklogn)

考虑 subtask6,发现 kst0,st1 没有一点关系,尝试把两者分离,但是推一推发现分离需要手写平衡树……

我们需要另一种写法,发现每次添加的都是最大值,移动都是移动集合中从小到大排序后的一段后缀,删除也是一段后缀,我们不需要 set 维护,只需要两个数组,维护这两个数组的前缀和,二分查找位置即可做到 O(nk+nlogn)

出处:https://www.cnblogs.com/Sktn0089/p/17615408.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   Lgx_Q  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示