Java教程

10.2 国庆集训测试

本文主要是介绍10.2 国庆集训测试,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Problem A

给两个数列 \(a_i,b_i\) ,你要找到一个排列 \(p\) ,使得每个 \(a_i \oplus b_{p_i} =x\) 都相等,其中 \(\oplus\) 表示异或,你要输出所有可能的 \(x\) 。

\(1\leq n\leq 2000,0\leq a_i,b_i \leq 10^9\)

先考虑如何判断一个 \(x\) 是否合法,通过移项:\(a_i\oplus x= b_{p_i}\) ,所以我们只需将 \(a_i\) 的每一项异或 \(x\) 后,判断序列 \(a\) 和 \(b\) 是否本质相同即可,时间复杂度 \(O(n\log (n))\) 。

又观察到 \(x\) 一定是 \(a_1 \oplus b_1,a_1\oplus b_2...a_1\oplus b_n\) 中的一个数(因为 \(a_1\) 一定会与一个数配对),所以只用判断这 \(n\) 个值即可时间复杂度 \(O(n^2\log(n))\) 。

Problem B

有 \(n\) 个球,每个球有 RGY 三种颜色,现在小 F 觉得如果有两个相邻的球颜色相同很丑,他每次可以交换相邻两个球,问至少交换多少次才能不丑。

\(1\leq n\leq 400\)

首先,如果知道最终序列,可以通过逆序对,快速得到交换次数。

观察得知,对于交换完的最终序列,同种颜色之间的相对顺序一定不变。所以设 \(dp(i,j,k,0/1/2)\) 表示在最终序列的前 \(i+j+k\) 项中, R 填了 \(i\) 个,G 填了 \(j\) 个,Y 填了 \(k\) 个,且第 \(i+j+k\) 个是 R/G/Y 时的交换次数。转移时只用枚举下一个位置填什么字符,因为前面的性质,可以轻松得知填的字符在原串中的位置,并计算这个字符对逆序对的贡献。

时间复杂度 \(O(n^3)\) 。

problem C

有 \(n\) 个人站成一个圈,每个人有 \(a_i\) 个球,下面要进行一次操作:
每个人把一些它的球交给它右边的人,所有人同时进行。
完了过后每个人有 \(b_i\) 个球,记这个序列为 \(B\) 。
于每种 \(B\) ,它的价值为 \(\prod bi\)。
对于所有可能的 \(B\) ,你要计算它们的价值和,对 \(10^9 + 7\) 取模。

\(n\leq10^6,0 \leq a_i \leq 10^9\) 。

设 \(c_i\) 为第 \(i\) 个人给它右边的人的球的个数,则 \(b_i=a_i+c_{i-1}-c_i\) ,不难发现如果 \(\max c_i \geq 1\) ,那么对所有 \(c_i\) 减 \(1\) 后得到的 \(b_i\) 不变,所以 \(c_i\) 中一定有 \(0\) 。所以我们枚举 \(c\) 中下标最大的 \(0\) 的出现位置 \(x\) ,并计算这样的所有方案的价值和。 因为 \(c_x=0\) ,所以我们在 \(x\) 和 \(x+1\) 之间断环成链,于是设 \(dp(i,j)\) 代表考虑链上的前 \(i\) 个人,第 \(i\) 个人给 \(i+1\) 个人 \(j\) 个球的价值和。转移为:

\[dp(i+1,j)=\sum_{k=0/1}^{a_k}{dp(i,k)\times (a_{i+1}+k-j)} \]

注意到因为 \(x\) 是小标最大的 \(0\) ,所以当前这个人的实际下标如果大于 \(x\) ,\(k\) 的下界就是 \(1\) 。但这样的复杂度不足以通过此题。

又观察到转移过程中只用维护 \(\sum_{k=0/1}^{a_k}{dp(i,k)\times k}\) 和 \(\sum_{k=0/1}^{a_k}{dp(i,k)}\) 即可,时间复杂度变成了 \(O(n^2)\) 。

注意到每次的转移系数都只和 \(a_i\) 有关,所以可以把每个位置的转移都写成一个矩阵,并处理前后缀积,复杂度 \(O(n)\) 。

这篇关于10.2 国庆集训测试的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!