E 想出来了,不过只有最后 5 min 了,以后还是得更快给出做法。
vp 赛时:ABCDF Accepted,Score:6734,Rank:38。
改题进度:All Accepted。
A
题意:给定字符串,字符权值为 $a\to z, 1\to 26$,每次轮流选,先手只能选长度为偶的子串拿走,后手只能选长度为奇的子串拿走,问最后谁得分高,高多少。
首先长度为偶数一定直接拿走。
长度为奇数直接选择少的一个不选即可。
B
题意:判断一个字符串是否满足以下条件:
设该字符串字符集为 $\sum$,那么任意子串均满足 $\forall c_1, c_2\in \sum, |\text{occ}(c_1) - \text{occ}(c_2)| \leq 1$,$\text{occ}(c)$ 表示 $c$ 在子串中出现的次数。
爆搜或者观察样例,容易发现一定是一个周期为 $\sum$ 的循环出现,否则一定不合法。
如果有打破规律的,那么一定是 $c_1c_2\dots c_1$ 而没有包括 $c_{\sum}$,这样出现次数差一定大于 1。
这个串合法是显然的。所以证明了这个是充分必要的。
C
题意:$T$ 组询问,给出一个数 $n$ 求使其由“回文数”加和的方案数。注意没有顺序,可以选择相同的数。$T\leq 10 ^ 4, n\leq 4\times 10 ^ 4$。
暴力 DP $O(n ^ 2)$ 似乎过不去,但是容易发现回文数的个数一定不多,打个表看题解发现只有不超过 500 个,随便完全背包即可。时间复杂度 $O(nm)$,$m$ 表示回文数的个数。
另外的问题:如果是有序的怎么做?没想到什么好的做法,只有记录有多少个 binom 一下,似乎是 $O(n^2 m)$。
D
题意:给定两个有限递增等差数列 $B, C$,求有多少个有限递增等差数列 $A$ 满足 $A\cap B = C$。有无穷多个输出 -1。$T(T\leq 100)$ 组询问,
首先考虑无解情况:如果 $d_B$ 不整除 $d_C$,显然无解。如果 $d_B$ 不整除 $st_C - st_B$,无解。如果 $C$ 的首尾项超出了 $B$ 的范围,无解。
接下来考虑无穷的情况。如果 $C$ 的尾项后面一项超出了 $B$ 的范围,那么 $A$ 的尾项就可以无限延伸,就是无穷。首项前面同理。
如果 $\text{lcm}(d_A, d_B)\not= d_C$,显然是不可能的,所以我们可以暴力判断 $d_C$ 的所有因子是否合法。时间是允许的。
如果是合法的,那么 $A$ 的首项应该在 $C$ 的首项和 $C$ 首项前一项之间,尾项同理。贡献就是 $(\dfrac {d_C}{d_A}) ^ 2$。
直接暴力计算即可。
1 | void solve(int ad) |
E
题意:给定 $n$ 的序列 $a_i = 2 ^ {b_i}$,可以在中间加入 $\oplus$ 或者是 $\texttt{Power}$,然后按照优先级计算,至少加入 $k$ 个 $\oplus$,问所有插入方式的计算答案的 $\oplus$,对 $2 ^ {2 ^ {20}}$ 取模,2 进制输出。$n\leq 2 ^ {20}, 1\leq b_i < 2 ^ {20}$。
可能与 tutorial 做法不一样。
考虑,然后按照一段区间算贡献。容易发现一段不包含 $\oplus$ 区间的答案只有可能是 $2 ^ x$ 的形式,于是看贡献次数是否是 2 的倍数。
考虑如果我们已经确定了一段区间,怎样计算贡献次数。如果两边都没有到头,那么相当于我们已经选择了两个端点,又强制一些不能选,那么就是 $\binom {len - 1}{k - 2}$,$len$ 表示没有被选择的区间。至少有 $k$ 个,就是 $\displaystyle \sum_{i = k - 2} ^ {len - 2} \binom{len - 2}{i}$(自己手玩一下。如果覆盖了一端,那么就是 $\displaystyle \sum_{i = k - 1} ^ {len - 1}\binom{len - 1}{i}$。覆盖了两端当且仅当 $k = 0$ 合法。
怎样快速计算这个呢?根据 Lucas 定理,那么相当于 $i\odot (len - 1) = i$ 贡献才为 1,那么我们可以使用 FMT 前缀和一下,就可以得到了。
直接暴力枚举区间是 $O(n ^ 2)$,但是容易发现不超过 20 次就会超出模数范围,也就是说,区间长度最多只有 20。于是暴力枚举即可,注意分讨。
1 | int main() |
F
题意:$n\times n$ 的网格,合理设计四联通相邻的网格边权,使得从任意已知起点走到任意点都能通过边权异或值得到终点位置。$n\leq 32$,边权和不得超过 $48000$。
比较有意思的位运算题目。一下默认 0 开始标号。
首先考虑 1D 情况,我们需要把大的 $bit$ 出现次数尽量小,那么比如 $n = 32$,我们就在 $15\to 16$ 的边上放上 16,此外都不放 16,这样我就能判断是在 $[0, 15]$ 还是 $[16, 31]$。向下同理,可以发现需要的边权和就是 $16 + 8\times 2 + 4\times 4 + 2\times 8 + 1\times 16 = 64$。
放到 2D 上,一个显然的想法是我们将两维分开,两维互不干扰,于是 $x$ 维上使用 $0, 1, 2, 3, 4$ 位,$y$ 维上使用 $5, 6, 7, 8, 9$ 位,这样整个的代价就是 $32\times 64 + 32\times 2048 = 67584$,不能通过。
$y$ 维上全是高位,贡献组合较大,我们可以考虑交叉使用,$x$ 维使用 $0, 2, 4, 6, 8$,$y$ 维使用 $1, 3, 5, 7, 9$,这样跑一下程序发现是 $47616$,于是可以通过。
1 | int main() |