Codeforces Round 921 Div 2
A - We Got Everything Covered!
很显然,最短的方案长度一定是\(n \times k\),直接循环输出即可。
1 | // Problem: A. We Got Everything Covered! |
B - A Balanced Problemset?
一个显而易见的结论是,如果答案是\(y\),那么一定有\(x \mid y\)。那么直接枚举\(x\)的因子,判断\(\frac y x\)是否大于等于\(n\)即可。时间复杂度\(\Theta(T\sqrt x)\)。
1 | // Problem: B. A Balanced Problemset? |
C - Did We Get Everything Covered?
一开始想了个最短路做法(写一半发现太麻烦了)。
可以用一个桶记录字母的出现情况,每次桶里前k个字符都不为空了,就清空桶,总轮数加一,记录下出现次数最少的那个字母(也就是最后一个字母)。最后再检查总轮数是否大于等于n。如果不满足,就在记录下的字母后面添任意字母,直到长度为n,输出即可。
下面是包含写fake了的最短路的代码(
1 | // Problem: C. Did We Get Everything Covered? |
D - Good Trip
题目作者的表述感觉emmm,最大的障碍是读懂题意?
令每轮老师选人前,所有可能被选中的两人队的友谊值期望为\(E_i\),题目其实就是让我们求 \[ \sum_{i=1}^{n}E_i \] 每次可能有\(\frac{n(n+1)}2\)个不同的队被选中,令有友谊值的朋友的友谊值和为\(sum_i\),总共\(k\)对朋友,那么很显然有: \[ E_i=\frac{sum_i}{\frac{n(n+1)}2} \] 然后\(sum_i\)的推导也很简单: \[ sum_i=sum_{i-1} + \frac{k}{\frac{n(n+1)}2} \] 直接简单递推就行了。
1 | // Problem: D. Good Trip |
E - Space Harbour
一个数据结构好题。
询问操作,很显然可以拆分为\(query(r)-query(l-1)\)的操作。那么我们考虑用树状数组维护每个点的贡献。
但是很显然,每次插入港口,都会对很多个位置的贡献造成改变,显然不能直接维护贡献。
考虑一下一整段点贡献的性质,很容易发现的是,对于两个港口\(pos_i,pos_{i-1}\)之间的位置,他们的贡献和可以表示为: \[ V_{pos_i} \times (1+2+3+\dots +(pos_i-pos_{i-1}-1)) \\\\ =V_{pos_i} \times \frac{(pos_i-pos_{i-1})(pos_i-pos_{i-1}-1)}{2} \] 考虑维护每一个坐标左边的最近港口的值,显然可以用树状数组差分完成。
那么,对于维护贡献,我们可以不维护全部点的贡献,转而维护连续整段的贡献。
具体的,我们算出两个港口之间答案的和,将这个答案存放在\(pos_i+1\)的位置上。这样,当查询\(x\)位置的贡献和时,对于整段区间,直接前缀和算出;对于结尾的小段,再单独计算即可。
然后是加入港口操作。显然,我们是把原来的一整段区间分成了两个区间。用个set维护港口的下标,求出上一个港口和下一个港口的坐标后,再更新一下两个树状数组即可。
这题小细节很多,要格外注意。
1 | // Problem: E. Space Harbour |