AtCoder Beginner Contest 257 Solution

更好的阅读体验戳此进入

题面链接

题面 Luogu 链接

abc 跳了

[ABC257D] Jumping Takahashi 2

题面

给定 n 个不共点的蹦床,第 i 个蹦床的位置为 (xi,yi),反弹力为 pi。存在整数 S。定义能从第 i 个蹦床跳到第 j 个蹦床当且仅当 pi×S|xixj|+|yiyj|。你需要钦定一个起点,使得可以从该蹦床抵达所有蹦床(可以多步),并最小化 S,输出最小值。

Solution

不难发现问题可以转化为,我们要选择一个点,求使得这个点能够到达其它所有点的最大代价,然后求所有起点最大代价的最小值,这东西有点像全源最短路,且数据范围很小。于是不难想到一步转化,可以将原不等式转化为 S|xixj|+|yiyj|pi,显然 S 存在单调性,所以自然可以令 S=|xixj|+|yiyj|pi。于是可以认为 ij 的边权即为这个,然后跑一遍 FLoyd,维护每个源点的最大值,最后取个最小值即可,复杂度 O(n3)。当然不用 Floyd,或者改用 bfs + 二分答案,都是可以做到 O(n2logn) 的,不过意义不大。

Code

[ABC257E] Addition and Multiplication 2

题面

高桥君有一个整数 x 。一开始的时候, x=0

高桥君可以无限执行以下操作:

高桥君有 N 日元,问 x 最大是多少?

Solution

在保证长度最长的前提下尽量在更高位选择更大的数即可。

Code

[ABC257F] Teleporter Setting

题面

存在 n 个小镇,m 条传送通道,第 i 条双向连结 ui,vi 两个小镇,经过每个传送通道需要花费 1 分钟。特别地,可能存在 ui=0,表示该条传送通道只规定了一端,另一端待定。存在 n 个独立询问,对于 i=1,2,,n,钦定所有未确定的 ui 均为 i,求从小镇 1 到小镇 n 最小耗费的时间。若无法到达输出 1

Solution

算是一道挺好的题。首先我们可以进行如下转化,对于所有 ui=0 的边,我们将其连结到一个超级源点 S 上,不失一般性,设 S=0,此时对于每次询问,我们仅需要对 Si 连边即可。当然我们肯定不能每次都算一遍,于是考虑发现,对于 1n 的路径,一共仅可能存在如下几种贡献:1n1Sin1iSn,同时注意我们这里的箭头不是表示直接到达,而是表示最短路。所以以此不难发现,我们所需要维护的就只有 1n 为源点的单源最短路,即可表示出来每次的值。然后每次在这些里取 min 即可,记得判一下无解。

Code

[ABC257G] Prefix Concatenation

题面

给定仅存在小写英文字母的字符串 S,T。你需要将 T 分割成 kS 的前缀(或着说用 S 的若干个前缀组成 T),最小化 k,输出最小值。若 k 不存在输出 -1

Solution

首先 O(n2) 的 DP 显然,我们记 S(i,j),T(i,j) 为对应字符串 [i,j] 的子串,令 dp(i) 表示考虑 T(1,i) 的最小 k。易得转移:

dp(i)=minj<iS(1,ij)=T(j+1,i)dp(j)+1

不难发现这个 1D1D 的 DP 是 O(n2) 的无法通过,考虑优化。

首先有一个思路,已知 dp(i) 单调不降,证明显然,考虑若 dp(i)>dp(i+1),那么在 dp(i+1) 的方案中将最后一部分去掉第 i+1 个一定可以变为 dp(i)k 不劣,得证。

然后根据这个思路我们每次转移只需要找到最小的合法 j 转移即可,可以通过 KMP 中的 next 数组维护。

具体地,不难发现我们这个东西求的可以转化为求 border,具体地,我们将 S 后追加一个占位符,然后再连接上 T,记 P = S + '#' + T,这样我们对 P 跑一遍 KMP 的建立 next 数组过程,不难发现对于转移 i 时需要的 j,即为 inxt(lenS+1+i),这里的 +1 即为我们添加的占位符 #

最终 DP 优化为 1D0D,复杂度 O(n),可以通过。

同时还有一种方法,发现修改状态为后缀可以支持逆序转移,于是转移变为:

dp(i)=minj>iS(1,ji)=T(i,j1)dp(j)+1

此时发现每次可以转移的 j 是连续的,对应 ST(i,lenT) 的 LCP,于是可以通过哈希 + 二分处理每次转移的 LCP 长度,然后线段树优化 DP 即可,最终复杂度 O(nlogn),劣于正向转移但也可以通过,且思路更直观,仅代码实现略长。

Code

[ABC257Ex] Dice Sum 2

题面

存在 n 个正六面体骰子,第 i 个骰子六个面的数值分别为 Ai,1,Ai,2,,Ai,6,购买第 i 个骰子的花费为 Ci。你要在其中购买 k 个骰子,以最大化收益的期望。定义收益为将购买的 k 个骰子各扔一遍,其朝上的数的和的平方减去买 k 个骰子花费的总费用。输出模 998244353 意义下的收益期望最大值。

Solution

果然难题的尽头是推式子。

首先令买的 k 个骰子为 A1,A2,,Ak,不难根据期望定义列出式子:

E=x1=16x2=16xk=1616ki=1kAi,xii=1kCi

然后考虑将中间的 i=1kAi,xi 转化一下,并去掉外面的一堆求和(关于这步,可以考虑钦定一个骰子为 A 时,剩下 k1 个骰子可以任选,即 6k1,而钦定两个骰子并钦定顺序之后则为 6k2),即:

E=16k(i=1kxi=166k1Ai,xi2+i=1kj=1kxi=16xj=166k2Ai,xiAj,xj×[ij])i=1kCi

然后将前面的分式带进去并进一步化简:

E=16i=1kxi=16Ai,xi2+136i=1kj=1kxi=16xj=16Ai,xiAj,xj×[ij]i=1kCi

发现 ij 难以处理,尝试通过类似容斥的思想,从平方中去除 i=j 的部分,化简为:

E=16i=1kxi=16Ai,xi2+136(i=1kxi=16Ai,xi)2136i=1k(xi=16Ai,xi)2i=1kCi

发现式子中出现了大量的 xi=16Ai,xi,考虑令:

Xi=16xi=16Ai,xi

然后发现第二项可以转化为:

136(i=1kxi=16Ai,xi)2=(i=1kXi)2

然后考虑一三项,同样尽量用 Xi 转化:

16i=1kxi=16Ai,xi2136i=1k(xi=16Ai,xi)2i=1kCi=i=1k(16xi=16Ai,xi2Xi2Ci)

此时若我们令:

Yi=16xi=16Ai,xi2Xi2Ci

则原式转化为:

(i=1kXi)2+i=1kYi

写的更明显一点,我们就是要求:

max{(X)2+Y}

显然购买方案一共有 (nk) 种,我们可以考虑将每一种购买方案抽象成二维平面中坐标为 (X,Y) 的点,记作 (x,y),那么我们也就是要在若干个点最大化 x2+y

显然我们是需要尽量使 |x|y 都大一些,所以最终可能成为答案的点一定在点集组成的上凸包中。所以理论上我们可以通过枚举每个实数斜率,然后以该斜率的直线去切这个凸包,截距最大的即为凸包上的点。这里理论上截距应该是 kx+y,但是为了便于计算我们可以认为是一条斜率为 k 的直线,那么截距即为 kx+y,同时注意这里我们只求截距最大值是因为只需要维护上凸包。具体来说就是对于每个 k 找到最大的 kX+Y,显然可以转化为对所有点求一次 kX+Y,然后从中选择前 k 大(注意这里的 k 不是斜率的 k,而是买的 k 个骰子)求和即可。

然后这里我们显然不能枚举实数,于是考虑什么时候骰子之间的大小关系会发生变化,考虑存在以下情况,当 kk 使得 i,j 之间顺序变化时显然有以下式子(举个例子,大小关系相反亦可):

kXi+Yi<kXj+YjkXi+Yi>kXj+Yj

显然对于这两种情况的转折点存在于:

k=YjYiXiXj

并且此时仅有 i,j 之间的大小关系会改变。

所以我们 O(n2) 枚举并预处理,然后遍历一下 k,第一次排个序,后面的 O(1) 修改即可,最终复杂度卡在排序上,为 O(n2logn2),可以通过。

Tips:实现时为了便于排序,且 X,Y 远小于 long long 的范围,我们可以考虑按照 (36X,36Y) 排序,这样就不可能有分数了,然后最后乘一个 36 的逆元即可。

Tips:还有一个我调了很久的细节,就是过程中不能取模,否则大小关系会变化,导致答案错误。

然后按照这个思路实现之后大概是这样:

看起来没什么问题,但是交上去就会发现错了很多点,感觉可能是精度之类的问题,于是我们考虑去掉所有浮点数相关运算。

首先对于初始的排序,不难想到若将 k 升序,那么我们可以认为初始 k=,则 Y 对大小关系影响忽略不计,仅比较 X 即可。

然后对于修改之间的排序把式子推一下换成乘法即可。还有个细节就是我们在修改的时候应仅保留一些满足 X 偏序关系的,可以大概理解为保证我们变的这个 k 是单调的,当然这个点我也没有完全弄明白,如果有大佬知道的话欢迎解惑。

Code

UPD

update-2022_12_19 初稿