CF1383(div1)(待补 C/D)

CF1383


A [* easy]

给定两个字符串 \(A\)\(B\),每次可以选取 \(A\)若干个相同的字符 \(x\),然后将其改成 \(y\),需保证 \(x<y\)

求使得 \(A=B\) 的最小操作次数。

数据组数 \(\le 10\)\(\sum |A|,\sum |B|\le 10^5\)\(A\)\(B\) 仅由 a \(\sim\) t 构成(共计 \(20\) 个)。

\(\rm Sol:\)

观察到字符只可以变大,所以从 \(a\)\(t\) 进行枚举,对于当前的全体 \(x\),每次直接增大的最小的目标即可。复杂度 \(\mathcal O(20\sum n)\)


B [* easy]

给定 \(n\) 个数 \(a_{1,2...n}\),Alice 和 Bob 玩游戏,两者初始权值均为 \(0\),Alice 先手,Bob 后手,轮流操作,每次拿走一个数,然后将其与当前权值进行异或,权值高者获胜。

问最优决策下,先手 win/lose/draw。

\(\rm Sol:\)

感觉是根据 \(1\) 的数量判。

从高位到低位进行枚举,对于当前位,假设有偶数个 \(1\),那么当前位无法分出胜负,只能考虑下一位(无论先后手怎么选,都有当前位的两者获得权值相同)

假设有奇数个 \(1\),那么必有一者获胜,假设 \(1\) 的数量为 \(4k+1\) 那么先手胜,否则考虑 \(0\) 的数量,奇数时后手胜。归纳即可。


C [* ]

给定两个字符串 \(A\)\(B\),每次可以选取 \(A\)若干个相同的字符 \(x\),然后将其改成 \(y\)

求使得 \(A=B\) 的最小操作次数。

数据组数 \(\le 10\)\(\sum |A|,\sum |B|\le 10^5\)\(A\)\(B\) 仅由 a \(\sim\) t 构成(共计 \(20\) 种字符)。

\(\rm Sol:\)

构造一张 \(20\) 个节点的图,对于每个 \(i\),连接 \(A_i\to B_i\)

问题变成给定一张图 \(G\)


D

构造,以后再说。


E [* easy]

给定一个 01 串 \(a\)\(n=|a|\),你可以执行不超过 \(n-1\) 次操作,每次为选择一个 \(i\in [1,|a|)\),然后令 \(a_i=\max\{a_i,a_{i+1}\}\),将 \(a_{i+1}\) 删除。

求你可以得到多少个串,答案对 \(10^9+7\) 取模。

\(\rm Sol:\)

考虑怎么样的一个串可以得到,首先发现一组 \(01\)\(10\) 都只能删 \(0\)\(11\)\(00\) 删的是谁我们其实不太关心。

然后发现最后剩余的串是 \(S\) 的子序列,然后发现一个 \(1\) 能被删除当且仅当这个 \(1\) 满足其两端存在至少一个 \(1\)

于是对于 \(S\) 的子序列 \(T\),其能够生成,当且仅当其中两个相邻的 \(0\) 之间没有 \(1\),然后假设以 \(0\) 开头/结尾,那么前缀/后缀没有 \(1\)

直接做不太好做,考虑进一步简化信息,对于相邻的两个 \(1\),我们记 \(pre_i\) 表示第 \(i\)\(1\) 和第 \(i-1\)\(1\) 之间的 \(0\) 的数量,同时补充结尾段(可以为 \(0\),如果 \(S\) 中不存在 \(1\) 特判),这样串 \(S\) 变成了一个序列 \(\{pre\}\) 接下来我们考虑如何判定一个串 \(T\) 能否生成。

类似的将 \(T\) 变成一个这样的序列,不难发现 \(T\) 合法当且仅当:

  1. \(T\) 的开头和结尾元素比 \(S\) 的开头/结尾元素小。
  2. 对于 \(T\) 的中间部分,可以与 \(S\) 匹配,即 \(S\) 存在一个子序列 \(\{b\}\) 满足 \(b\) 的对应元素均大于等于 \(T\) 的对应元素。

那么可以类似于子序列自动机的做法来 dp,去除开头/结尾部分后,对中间部分进行 dp。

考虑在位置 \(i\) 填入 \(j\) 时,从 \(k\) 处转移的条件为 \([k+1,i-1]\) 这个区间内不存在 \(pre_x\ge j\),那么可以维护一下对于每个 \(j\),最大的满足条件的 \(x\) 即可(每次处理完一个 \(i\) 后暴力更新即可)。

然后用前缀和优化一下转移,就做完了。复杂度是 \(\mathcal O(\sum pre_i)=\mathcal O(n)\)

不难发现这个算法默认序列中存在至少一个 \(1\),所以要特判全 \(0\)


F

给定一张 \(n\) 个点 \(m\) 条边的无向图 \(G\),给定 \(k\) 条特殊边,进行 \(q\) 次查询,每次给定这 \(k\) 条边的权值,查询这个状态下 \(1\to n\) 的最大流。

\(n,m\le 10^4,k\le 10,q\le 2\times 10^5\)

\(\rm Sol:\)

观察到最大流等于最小割,所以可以枚举这 \(k\) 条边被割/不被割,对于被割,将这条边的边权设为 \(0\),否则设为 \(\infty\)

然后跑最大流可以进行预处理,然后可以轻易的做到 \(\mathcal O(2^k)\) 进行查询,复杂度为 \(\mathcal O(2^k\cdot \textrm{maxflow}(n,m)+q\cdot 2^k)\)

事实上,可以预处理不含这 \(k\) 条边时的最大流的残量网络,然后每次在这个网络上增广即可,注意到插入的边权和很小,可以考虑采取 EK/FF 算法来解决此问题,复杂度为 \(\mathcal O(2^k\times wm)\)

然后由于 Hack 数据,转移的时候不能暴力加边,而是要枚举最小的 bit 转移过来。

然后这个题就做完了。


posted @ 2020-09-13 17:51  Soulist  阅读(164)  评论(0编辑  收藏  举报