国外训练试题泛做

\(36th\ Petrozavodsk\ Programming\ Camp , 300iq\ contest\ 3\)

\(F\)

首先如果选择 \(i\) , 记花费在 \(i\) 上的有 \(r_{i}\) 次 , 则 \((h_{i} - r_{i} \cdot a)\ mod\ b < a\)

发现 \(r_{i} = \lfloor \frac{(h_{i}\ mod\ b)}{a} \rfloor\)。 那么得分至少要花费 \(r_{i} + 1\) 次。

注意到如果选择 \(i\) 个物品也只需花费 \(r_{i} + 1\) 次 , 因为多花费显然不优。

那么就有一个反悔贪心的思路了。 每次假定不选择 , 将决策放入小根堆 , 每次将堆顶与当前的决策比较即可。

时间复杂度 : \(O(NlogN)\)

\(J\)

首先每个点可以看成一个线性同余方程 , 因此这个题目的本质是求一个线性同余方程组的自由元个数。

任取一棵生成树 , 注意到在非树边确定的情况下树边的权值是确定的。 并且每个点权值向上的贡献是一个正负交替的形式。 因此还要

额外保证奇数深度和偶数深度的点权和相等。 这里的 "点权" 指的是相邻的边权和。

换言之 , 就是对于一个连通分量 , 如果它是二分图 , 那么贡献是 \(2 ^ {|E| - |V| + 1}\) , 否则是 \(2 ^ {|E| - |V|}\)

时间复杂度 : \(O(N)\)

\(I\)

每个数被统计当且仅当这个数没有 \(a_{1} \oplus a_{2} ... \oplus a_{i - 1}\) 中的位。

直接考虑每个数的贡献即可。

时间复杂度 : \(O(NlogV)\)

\(H\)

题目可以抽象为两种操作 :

\(0.\) 在右侧加点。

\(1.\) 在左侧加点 , 向右侧所有点连边。

这样所给的 \(a\) 序列就可以转化为一个 \(0\)\(1\) 的交错操作序列。

注意到最后答案的形式必然是 \(010101010.....\) 这样的形式。

不妨记 \(dp_{i , j}\) 表示考虑了操作序列的前 \(i\) 个操作 , 当前形成了 \(j\) 条链的方案数。

每次如果是在右侧加点 , 那么这个点与当前左侧所有点都没有连边。 有两种决策 :

\(1.\) 单独成一条链。

\(2.\) 添加在之前某条链的末尾。

如果加入的是左侧点 , 那么该点与右侧所有点都有连边 , 有两种决策 :

\(1.\) 什么都不做。

\(2.\) 合并两条链。

这样分析后 , 这个动态规划就很容易转移了。

注意对于一个环而言 , 其正向和反向都被记了一遍 , 所以答案要除以二。

还需减去二元环的个数 , 为 \(\sum{a_{i}}\)

时间复杂度 : \(O(N ^ 2)\)

\(B\)

记度数为 \(1\) 的点有 \(x\) 个。

答案为 \(min\{\frac{N}{2} , N - x\}\)

证明略。

时间复杂度 : \(O(N)\)

\(ICPC\ World\ Final\ ,\ 2020\)

\(A\)

首先只有 \(p\) 值相同的才能改变位置。

于是将两排都按 \(p\) 值从小到大排序。 用 \(std::set\) 维护当前两个集合。 当 \(ap_{i} \neq ap_{i + 1}\)\(bp_{i} \neq bp_{i + 1}\) 时 , 在 \(set\) 里二分构造方案即可。

时间复杂度 : \(O(NlogN)\)

\(G\)

建立反串的 \(AC\) 自动机。 并将询问串也倒着插入。

对于每个给定字符串 , 将其沿着 \(fail\) 树一路的标记都 \(+1\)

那么最后询问的就是每个终止节点的标记。

树上差分即可。

时间复杂度 : \(O(N)\)

posted @ 2020-11-07 11:57  evenbao  阅读(112)  评论(0编辑  收藏  举报