任务1

P12304 [ICPC 2022/2023 WF] 过桥

题解

水黑题。

首先按照过河速度从小到大排序,我们发现过河无非就是让若干小的提前到河对岸准备跑腿回来。

也就是说过河只有这几种情况:

  1. \(k\) 小的人过河
  2. \(k\) 小的人带着 \(c-k\) 个累赘过河(\(k\) 可以为 \(0\)

显然可以 \(\text{dp}\),我们做一下代价前置。

\(dp[i][j]\) 代表把前 \(i\) 小的人送过河,还有 \(j\) 次跑腿机会(这个可以理解为代价前置),所需要花的最少时间(显然 \(j\le n/c\)),则有方程:

\[dp[i][j+k-1]=\min(dp[i][j+k-1],dp[i][j]+a[k]+s[k]);\\ dp[min(i+c-k,n)][j+k-1]=\min(dp[min(i+c-k,n)][j+k-1],dp[i][j]+a[\min(i+c-k,n)]+s[k]); \]

然后就做完了。

时间复杂度 \(O(n\times (n/c) \times c)=O(n^2)\)

P12297 [ICPC 2022/2023 WF] 三种骰子

题解

套路题。

首先判断哪个骰子占优就不用说了吧,随便双指针做一下。。。

然后两个问其实没啥区别,我们就以对于比 \(D_1\) 占优的 \(D_3\)\(score(D_3,D_2)\) 最少为多少,这个会了别的也会了。

然后我们注意到离散化后,就只有 \(O(n)\) 个点数是有用的,毕竟我们只关心相对大小,我们对于每一个点,显然也可以预处理出来这个点数对每个骰子期望得分是多少,令 \(i\) 这个点值对 \(D_1\) 的期望的得分为 \(a_i\),对 \(D_2\) 的期望得分是 \(b_i\)

我们也就是要调出来若干个数 \(c_i\),使得在保证 \(\frac{\sum a_{c_i}}{|c|}\ge\frac{1}{2}\) 的情况下,并最小化 \(\frac{\sum b_{c_i}}{|c|}\),首先我们对后者二分答案,也就是我们要 \(\text{check}\) 是否能做到 \(\frac{\sum a_{c_i}}{|c|}\ge\frac{1}{2},\frac{\sum b_{c_i}}{|c|}\le ans\)。根据平均值的经典 \(\text{trick}\),我们给 \(a_i\) 都整体减去 \(\frac{1}{2}\)\(b_i\) 整体减去 \(ans\),我们就只需要判断是否能做到挑出若干个数使得 \(\sum a_{c_i}\ge0\)\(\sum b_{c_i}\le0\),显然只要存在一个数 \(i\) 满足 \(a_i\ge0\)\(b_i\le0\) 就直接合法了,如果不存在呢,我们注意到因为可以挑无限多面点数,我们只会选择 \(a<0\)\(b<0\) 的某个点,和 \(b>0\)\(a>0\) 的某个点,一共只选择两个点。我们令前者点数是\(i\),后者是 \(j\),并且前者有 \(x\) 个,后者有 \(y\) 个,那么推下式子显然有:

\[xa_i+ya_j\ge0\\ xb_i+yb_j\le0 \]

可以推得:

\[\frac{b_i}{b_j}\le\frac{-y}{x}\le\frac{a_i}{a_j} \]

显然只要满足 \(\frac{b_i}{b_j}\le\frac{a_i}{a_j}\),也就是 \(\frac{a_j}{b_j}\ge\frac{a_i}{b_i}\),就一定存在合法的 \(x,y\)。我们也就只需要判一下所有 \(a>0,b>0\) 的点中 \(\frac{a}{b}\) 最大的是否大于 \(a<0,b<0\) 的点中 \(\frac{a}{b}\) 最小的,如果存在就代表合法,然后就这么 \(\text{check}\) 就做完了,时间复杂度是 \(O(n\log V)\) 的。

P9382 [THUPC 2023 决赛] Freshman Dream

题解

不是题。

非常显然,对于 \(B\) 矩阵的某一列 \(k\),我们都能列出只和这个列元素有关的 \(n\) 个方程:

\[\begin{cases} a_{1,1}b_{1,k}+a_{1,2}b_{2,k}+\cdots a_{1,n}b_{n,k}=a_{1,k}b_{1,k}\\ a_{2,1}b_{1,k}+a_{2,2}b_{2,k}+\cdots a_{2,n}b_{n,k}=a_{2,k}b_{2,k}\\ \ \vdots \\ a_{n,1}b_{1,k}+a_{n,2}b_{2,k}+\cdots a_{n,n}b_{n,k}=a_{n,k}b_{n,k}\\ \end{cases} \]

因为对 \(2\) 取模了,加号都可以改成异或,所有系数如果是 \(0\) 我们就把这项忽略掉,这样我们就能手动算出关于这一列的异或方程组,直接拿 \(\text{bitset}\) 优化线性基我们可以 \(O(\frac{n^4}w)\) 解出这个异或方程组,因为保证数据随机了,所以自由元几乎特别少,我们可以直接 \(2^x\) 次方枚举自由元填什么(\(x\) 为自由元数量),得到解出这一列填多少个 \(1\) 是可能合法的,处理完这个就是一个典型的背包问题了,我们背包求解下方案就能做完了。

然后这里我们在简略证明一下 \(x\) 的数量级。

假设当前有 \(d\) 个互相线性不相关的方程组,也就是说他们张成的线性空间大小为 \(2^d\),我们有 \(\frac{1}{2^d}\) 的概率添加一个和他们线性相关的方程组,于是我们就可以 \(\text{dp}\) 了,令 \(dp[x]\) 代表有 \(x\) 个方程出现线性相关的方程的个数(也就是自由元的个数),那么就有 \(dp[x]=dp[x-1]+\frac{1}{2^{x-1-dp[x-1]}}\),最后发现 \(dp[100]\) 也就 \(1,2\) 左右,我们也就可以愉悦通过这道题了。

P9439 [ICPC 2021 WF] Crystal Crosswind

题解

垃圾题。

求出来哪些点必须是有分子,哪些点必须没有分子,剩下的点显然可以全是有分子的,也可以全是没有分子的,那么我们就相当于把答案求出来了。

那么如何求呢,简单 \(\text{bfs}\) 就好了。

对于一个点 \((x,y)\),若已经确定是有分子的,对于所有风向 \((w_x,w_y)\),若它是边界,那么有 \((x-w_x,y-w_y)\) 没有分子,否则就必须有分子。

对于一个点 \((x,y)\),若已经确定是没有分子的,对于所有风向 \((w_x,w_y)\),若它是边界,那么有 \((x+w_x,y+w_y)\) 一定没有分子(或者有分子,就是直接给出来的那些分子特判一下就好了)。

然后起点就是所有给出来的分子显然是有分子的,所有按照风向超出地图边界的但是自身却不是“边界”的显然不能有分子,然后按照这个 \(\text{bfs}\) 就做完了。

P9440 [ICPC 2021 WF] Dungeon Crawler

题解

贪心题。

无解是简单的,如果以 \(S\) 为根时,\(t\)\(k\) 的祖先,就肯定无解了,注意这道题 \(O(qn)\) 可以通过所以可以直接暴力跳判断,我们只需要预处理好对于每个点作为根的时候每个点的父亲是谁就好了。

然后呢,假如必须要最后回到根,显然答案就是 \(2sum\),其中 \(sum\) 为所有边边权和,如果没有 \(k,t\) 的限制,我们就留一个最长链,然后不回来就做完了,答案就是 \(2sum-w_{max}\)。考虑添加这个限制该怎么做,我们发现只有最长链经过了 \(lca(k,t)\) 的时候才会出现问题,因为 \(k\)\(lca(k,t)\) 这一段的链上必然要走至少两遍(显然必须要先走 \(k\) 后走 \(t\),已经折返了两遍),所以这种情况我们单独判一下这种情况和不经过 \(lca(k,t)\) 的最长链,哪个省下的距离更长就好了,后者不必多说,前者需要多走一份 \(u\)\(lca(k,t)\) 的路(\(u\) 为最深的在 \(k\)\(lca(k,t)\) 链上的点),我们令 \(u\) 到最远的叶子的长度是 \(dis_u\),我们只需要找出最大的 \(dis_u-dis(u,lca(k,t))\) 就好了。作比较看哪个最省就减哪个就做完了。时间复杂度是 \(O(qn)\)

P9441 [ICPC 2021 WF] Fair Division

题解

数学题。

随便化化式子,显然第 \(i\) 个人拿到的钱是:

\[(1-f)^{i-1}fm+(1-f)^{i-1+n}fm+(1-f+2n)^{i-1}fm... \]

这显然是个等比数列的形式,化简一下等于:

\[\frac{(1-f)^{i-1}-(1-f)^{+\infty}}{1-(1-f)^n}fm \]

\(g=1-f=\frac{q}{p}\),然后再做一些化简则有:

\[\frac{(1-f)^{i-1}-(1-f)^{+\infty}}{1-(1-f)^n}fm\\ =\frac{(\frac{q}{p})^{i-1}}{1-(\frac{q}{p})^n}fm\\ =\frac{(q^{i-1}\times p^{n-i+1})}{p^n-q^n}fm \]

我们想要对于任意式子都让这个数是整数,显然因为 \(p,q\) 互质,所以 \(p^n-q^n\)\(p,q\) 都互质,这个是显然的(你可以想更相减损法)。然后我们就必须让 \(fm=\frac{p-q}{p}m\) 能够整除 \(p^n-q^n\),因为 \(m\) 不是很大,然而 \(n\) 至少是 \(6\)\(p^n-q^n\) 想要小于 \(m\)\(p,q\) 最大也只能是 \(5000\),所以我们只需要 \(O(n^2)\) 枚举 \(p,q\) 判一下是否整除就好了。

P9443 [ICPC 2021 WF] Hand of the Free Marked

题解

神秘题。

注意到这道题等价于,我们给若干个局面(排列加上一张倒扣的牌的花色)对应上一种答案(答案是一个集合,显然答案要包含这个排列,以及除了排列的那张牌花色要能对应上)。这天然就是一个二分图匹配的形式,把若某个答案包含某个局面,就把这个答案和局面连边,它的最大匹配就是就是我们能猜出答案的集合数,只要再除以总集合数就是成功率了。

问题是如何求最大匹配,暴力建图网络流显然会超时,我们就需要发现一些性质。

首先这道题需要使用 \(\text{Hall}\) 定理,考虑到同学都不会这个定理,我来讲解并证明一下这个定理。

\(\text{Hall}\) 定理大概阐述,给定一个二分图,我们姑且令左部点小于右部点,若在左部点任意取 \(k\) 个点,都有这 \(k\) 个点连向的右部点的个数大于等于 \(k\),那么这个图一定能完美匹配,或者说这个图的最大匹配是左部点点数、

证明很简单,对于左部点只有一个点的图显然成立。我们令 \(N(S)\) 表示左部点集合 \(S\) 的邻集。假设左部点个数小于 \(n\) 的图成立,对于左部点个数是 \(n\) 的满足这个性质的图:

  1. 假如对于任何 \(S\subsetneq U,|N(S)|>|S|\)\(U\) 为左部点的全集),我们任意选择两个点匹配,并且在原图上面删除这两个点,剩下的子图显然每个左部点集对应的邻集大小最多比删之前少一,显然还是满足性质的,根据归纳法,剩下的子图存在完美匹配方案,所以原图存在完美匹配方案。
  2. 假如存在 \(S\subsetneq U,|N(S)|=|S|\)\(U\) 为左部点的全集),显然 \(S\) 单独满足这个性质,根据归纳 \(S\) 里的点集存在完美匹配,把 \(S \cup N(S)\) 从原图删去,剩下的子图仍然满足性质,根据归纳 \(U/S\) 也有完美匹配,所以整个图存在完美匹配方案。

我们证明 \(\text{Hall}\) 定理有什么用呢,我们回来观察我们建出来的二分图,显然可以分成若干个联通块(每个联通块中的右部点花色构成显然是相同的),显然对于每个联通块,所有的右部点度数是相同的,另外对于所有左部点假如我们按照倒扣的牌花色分类,同一类的左部点显然度数相同,我们现在可以证明对于每一个联通块都能完美匹配。

令每一列不同的左部点分别有 \(a_1....a_l\) 个,且每个右部点对每一类左部点的连边数目分别为 \(d_1...d_r\),则反过来每一类左部点对右部点的连边数目为 \(\frac{|R|d_i}{a_i}\)

若左部点点数大于右部点,对于每个右部点子集 \(S\),其在每一类左部点的出边数目至少为 \(|S|d_i\),连到的左部点个数至少为 \(\frac{|S|d_ia_i}{|R|d_i}=\frac{|S|a_i}{|R|}\),对这个式子做一个求和,就能得到连接的左部点总数是 \(\frac{|S||L|}{|R|}>|S|\),根据霍尔定理,最大匹配数就是右部点点数。

若左部点点数小于右部点,对于每个左部点子集 \(S\),假设其在每一个点中分别对应 \(S_1,S_2..S_l\),那么对于一个 \(S_i\) 来说,其到右侧的边数至少为 \(\frac{|R||S_i|d_i}{a_i}\),那对应的右部点数就是 \(\frac{|R_i||S_i|}{a_i}\),取所有 \(i\)\(\frac{|S_i|}{a_i}\) 最大的那个,设这个值为 \(k\),则 \(S\) 向右至少有 \(k|R|\) 个顶点,显然总点数 \(|S|\) 一定小于 \(k|L|\),然后我们就证明了这个图一定是完美匹配的。

所以我们可以直接暴搜搜索答案的花色构成,\(m,k\) 很小,显然不多,然后我们需要求出来左部点和右部点的个数然后好取 \(\min\),显然右部点的个数是 \(s=\prod_{i=1}^m \binom {a_i} {c_i}\),左部点的个数是 \((k-1)!\sum_{i=1}^ms_i\frac{c_i}{a_i-c_i+1}\)。然后就做完了。

P9446 [ICPC 2021 WF] Prehistoric Programs

题解

简单题。

对于括号题有经典转化就是把 ( 视为 \(+1\))视为 \(-1\),合法括号序列就必须保证每一个前缀和都 \(\ge 0\)。然后对于每一个输入的括号串,我们都提前处理好这个括号串最小的前缀和是多少(即这个括号串至少前面有多少个左括号才可以接到后面),以及 \(s[n]\) 是多少(这个括号串可以积累/消耗多少左括号)。然后就是简单贪心了,显然我们要先放积累左括号的括号串,在积累左括号的括号串中,我们按照对左括号需求从小到大排序,一个一个接到后面,显然如果有一个不能接就不合法了。对于消耗左括号的括号串,我们可以按照“微扰”法证明贪心顺序,对于两个消耗左括号的括号串 \(i,j\),令它们对左括号的需求(最小前缀和)是 \(x_i,x_j\),对左括号实际的消耗值(\(s[n]\))是 \(y_i,y_j\),显然交换 \(i,j\) 对前后的括号串是否能合法没有任何影响。现在我们要让这对括号串都合法假如 \(i\) 必须放在 \(j\) 前面,假设当前已经积累了 \(z\) 个左括号,那么一定有 \(z-y_i\ge x_j\)\(z-y_j<x_i\),也就是说 \(x_i-y_i\ge x_j+y_j\),所以我们按照 \(x_i-y_i\) 的顺序从大往小排一定是不劣的,还是如果中间出现不合法的就无解了。

P7602 [THUPC 2021] 视频倍增期

题解

板子题。

二分套主席树做完了,无需多言。

P7603 [THUPC 2021] 鬼街

题解

科技题。

首先显然,最多只会单调操作 \(6\) 个数,我们姑且定义常量 \(k=6\) 方便分析时间复杂度。

这道题是折半报警器,核心思想大概是根据鸽笼原理,假如一个报警器报警了,那么设这个报警器管辖的点是 \(t_1,t_2...t_k\),那么一定有 \(t_{max}\ge \lceil \frac{y}{k}\rceil\),所以我们把报警器都挂到点上,并且设置一个初步阈值即 \(\lceil \frac{y}{k}\rceil\),并按照初步阈值排序,每次单点加的时候,把所有超过初步阈值的报警器弹出来,暴力检测这些报警器是否报警,如果报警直接输出,如果不报警,那么重新更改报警器的阈值(改为 \(\frac{y-\lceil \frac{y}{k}\rceil}{k}\)),把报警器挂在点上需要自动支持按照是否快达到阈值排序,而且可能还得做弹出之类的操作,所以可以使用优先队列,如果报警了,可以对这个报警器编号打好删除标记,之后如果优先队列堆顶有删除标记就直接弹掉。分析一下时间复杂度,操作 \(1\) 对维护每个单点的值直接暴力就好了,时间复杂度 \(O(qk)\),然后是关于报警器的维护,对于每个报警器被去除一次,直接发现报警了是最好的,如果没报警,它的阈值其实也相当于变成了它的 \(\frac{k-1}{k}\),所以其实最多每个报警器被取出来 \(\log_{\frac{k}{k-1}}y\) 次,每次取出来需要检查每个单点是否报警,这个是 \(O(k)\) 的,然后还要把带有新的初步阈值的报警器重新放到堆里这个是 \(k\log n\) 的,是时间复杂度是 \(O(qk\log_{\frac{k}{k-1}}y\log n)\),时限给的挺长,在加上很多地方其实跑不满,总之可以通过此题。

P7604 [THUPC 2021] 形式语言与自动机

题解

性质题。

吐槽一句,非常妙妙,怎么出出来这么多性质的, \(O(n\log n)\) 做法非常 \(\text{naive}\),我们提供一个线性做法。

首先还是经典括号问题的转化,把 ( 视为 \(+1\))视为 \(-1\),合法括号序列就必须保证每一个前缀和都 \(\ge 0\)

我们令 \(u\) 段结尾的位置是 \(j\)\(v\) 段结尾的位置是 \(i\),显然有 \(0\le j<i,i<n\),根据那一个前缀和的要求,我们能非常自然地写出 \(i,j\) 合法的条件。

  1. \(\min_{k=0}^js[k]\ge0\)
  2. \(s[u]+\min_{k=i+1}^ns[k]-s[i]\ge0\)
  3. \(\min_{k=j+1}^is[k]-s[i]\ge0\)

我们就是要求出来有多少个满足条件的点对 \((i,j)\),我们现在考虑枚举 \(i\),考虑有多少个 \(j\) 合法。

首先观察式子 \(1\),这个其实是对右端点做出了限制,显然我们可以预处理出来最后一个前缀前缀和全都大于等于 \(0\) 的位置 \(r\),显然有 \(j\le\min(r,i-1)\)

然后我们观察式子 \(2\),我们发现 \(\min_{k=j+1}^i\) 显然在 \(i\) 固定时是单调的,显然 \(j\) 越往左,区间 \(\min\) 越小,所以这条限制其实就是对左端点产生了限制。如何求这个左端点呢,朴素的想法是二分,但是实际上我们发现这括号序列前缀和是有很优美的性质的,就是相邻两项必然只差 \(1\),所以任何两个取值是连续的,我们可以画出折线图。

我们可以维护一个数组 \(lst[x]\) 表示上一个前缀和值为 \(x\) 的位置,我们直接求 \(lst[s[i]-1]\),这个显然就是我们的 \(l\) (\(j\) 的取值范围的左端点),因为如果 \(j\) 再靠左 \(\min_{k=j+1}^i\le s[i]-1\) 一定不合法,这还没完,我们现在仍需判断 \(s[l+1]\) 是否大于 \(s[l]\),因为是折线,如果大于的话,那么从 \(s[l+1]\)\(s[i]\) 都一定大于等于 \(s[i]\),否则就都一定小于 \(s[i]\) 也就是无解。

现在我们已经求出来 \(l,r\),现在我们就只剩 \(2\) 这条限制了,我们也就是要求出来 \([l,r]\) 范围内有多少值 \(\ge s[i]+\min_{k=i+1}^ns[k]\) 。首先我们观察到一个性质,就是那个后缀最小值是定值,因为对于在最靠右全局最小值左面的点,一定后缀最小值是这个全局最小值,对于最靠右全局最小值后面的点,一定没有贡献,因为考虑式子 \(3\),显然 \(l\) 一定要在最小值右面(否则包含最小值一定不合法),如果最小值等于 \(0\),那这个全局最小值的位置一定是 \(n\),也没有在它右面的,否则的话一定小于 \(0\) 了,那么 \(l>r\) 肯定没有解。

为了方便,现在我们设 \(\min_{k=i+1}^ns[k]\)\(x\)。现在我们要分类讨论了:

第一种情况是 \(i\le r\) 的情况,对于这种情况必然有 \(s[l]=s[r]\),我们现在维护两个数组,分别是 \(dp[k]\) 代表 \(k\) 前缀前缀和中大于等于 \(s[k]\) 的数的个数,这个非常好维护,因为有式子 \(dp[k]=dp[lst[s[k]]]+1+[s[lst[s[k]]]<s[lst[s[k]]]+1]*(k-lst[s[k]]-1)\)。下一个是 \(lxt[k]\) 代表上一个前缀和为 \(k+x\) 的位置这个在和维护 \(lst\) 的时候同步维护一下就好了,那么这种情况贡献就是 \(dp[lst[s[i]]]+s[lst[s[i]]]+1]*(i-lst[s[i]]-1)-dp[lxt[l]]\)。这个中间有非常多细节,必须各种 \(lst,lxt\) 数组是否为空之类的,暂且不阐述。

第二种情况是 \(i>r\) 的情况,对于这种情况根据我们推理 \(x\) 是定值的那个办法,我们仍然能够推出只有前缀最小值的点才有可能对答案有贡献,那么 \(l\) 必定等于 \(0\)。所以答案直接就是 \(dp[lst[s[i]+x]]\) 了(我们令 \(lst\) 数组在 \(i>r\) 之后就停止更新),然后还是判一下各种是不是空的之类的细节啥的,

然后我们就做完了,时间复杂度 \(O(n)\)

posted @ 2025-10-11 08:34  Cybher  阅读(4)  评论(0)    收藏  举报