Codeforces Round #456 (Div. 2)

Codeforces Round #456 (Div. 2)

A. Tricky Alchemy

题目描述:要制作三种球:黄、绿、蓝,一个黄球需要两个黄色水晶,一个绿球需要一个黄色水晶和一个蓝色水晶,一个蓝球需要三个蓝色水晶,现有\(A\)个黄色水晶和\(B\)个蓝色水晶,要制作\(x\)个黄球,\(y\)个绿球和\(z\)个蓝球,还需要多少个水晶?

solution
\(max(0, x*2+y-A)+max(0, z*3+y-B)\)

时间复杂度:$ O(1) $

B. New Year's Eve

题目描述:在\(1\)~\(n\)中选不多于\(k\)个数,使选出来的数的异或和最大,输出最大值

solution
\(k=1\)时,最大值为\(n\)。 当\(k>1\)时,令LG为大于n的最小的\(2\)的幂,则一定存在两个数(例如\(n\)\(LG-1-n\),其中\(LG-1-n\)<\(n\))使得它们的异或和为\(LG-1\),即最大值为\(LG-1\)

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

C. Perun, Ult!

题目描述:你在玩一个游戏,在游戏中你只有一次攻击的机会,你的攻击值为\(damage\),当你攻击时,所有敌人都会受到伤害,假设攻击后有\(s\)个敌人死亡,那么你的得分为\((bounty+increase*t)*2\),其中\(t\)为你攻击的时刻,\(t\)为整数,其余值均为给定常数。每个敌人有三个属性:最大生命值\(max_health\),初始时的生命值\(start_health\),单位时刻恢复的生命值\(regen\)。当一个敌人的生命值小于等于\(0\)时,敌人死亡。游戏开始后还有\(m\)个更新信息,每个更新信息为:在\(time\)时刻,敌人\(enemy\)的生命值更改为\(health\)。问你的得分最大值,当最大值为无穷时,输出\(-1\)注意\(increase, regen\)可能等于\(0\)

solution
每个敌人的生命值与时间的关系可看做一条折线,再作直线\(y=damage\),显然得分最高的时刻会在交点处取得。

现先判断最大值为无穷的情况
1、若 \(increase=0\),则不可能无穷
1、若 \(increase \neq 0\),且\(damage \geq max_health\)对所有敌人成立,则最大值为无穷
2、若 \(increase \neq 0\),且某个敌人的\(regen=0\),最后一次更新的生命值\(health \leq damage\),则最大值为无穷

判断完无穷的情况后,将所有更新信息(将初始生命值看做时刻\(0\)的更新信息)按敌人为第一关键字,时刻为第二关键字排序。计算交点时刻,同时记录该交点为哪个敌人,若不存在交点,但该敌人可被消灭,则将该段折线的最后时刻(\(regen=0\)时为inf,即一个比较大的数)看做交点。
将交点按时刻排序,更新信息按时刻排序。按交点时刻进行扫描,同时维护该时刻可消灭的敌人数目,更新答案。具体维护操作为:根据更新信息判断在该时刻,某个敌人的可消灭状态是否改变,更新答案后,该交点的敌人视为不可消灭。

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

D. Fishes

题目描述:有一个\(n*m\)的鱼塘分成一个个\(1*1\)的格子,每个格子最多只能有一条鱼。有一个\(r*r\)的网,捕鱼时若网的左上角在格子\((x, y)\),则\((x, y)\)\((x+r-1, y+r-1)\)的鱼都能捕到,注意:整个网必须在鱼塘内。现要在鱼塘中放\(k\)条鱼,使得随机撒网时捕到鱼的数目的期望值最大。

solution
如果我们把每个格子能被多少种撒网方式覆盖写成一个函数\(f(x, y)\),则

\[f(x, y)=[min(n-r+1, x)-max(x-r, 0)][min(m-r+1, y)-max(y-r, 0)] \]

期望值

\[E=\frac{1}{(n-r+1)(m-r+1)} \sum f(x_k, y_k) \]

若固定鱼的\(x\)坐标,则\(f(x, y)\)关于\(y\)为一个单峰,且在\(y=\frac{m+1}{2}\)时有最大值。所以可以用一个优先队列来维护最大值,优先队列初始元素为每一行的\(\frac{m+1}{2}-1\)\(\frac{m+1}{2}\),即\(n*2\)个元素,每次取出最大值,然后将它左或右(本来向左的为左,向右的为右)的元素添加到优先队列。

时间复杂度:\(O((n+k)log(n+k))\)

还有另外一个方法:注意到其实整个二元函数是一个以\((\frac{n+1}{2}, \frac{m+1}{2})\)为顶的一个山峰,所以初始元素可以只有一个元素:山顶,然后每次取出最大值后把它邻近的四个格子都添加到优先队列里,但要注意判重。

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

E. Prime Gift

题目描述:有\(n\)个不同的质数,求第\(k\)小的数满足它的所有质因数都属于这\(n\)个数。\(n \leq 16\), 数据保证答案小于\(10^18\)

solution
首先可以用二分将问题转化为判断性问题,即求\(x\)内有多少个数满足条件。
若这\(n\)个质数为最小的\(16\)个质数,则\(10^18\)内有\(755,104,793\)个数满足条件,但若为\(8\)个质数\(2, 5, 11, 17, 23, 31, 41, 47\),或\(3, 7, 13, 19, 29, 37, 43, 53\),则对应个数为\(1,119,429\)\(500,675\)。所以可以将\(n\)个质数从小到大排序,然后分成偶数位和奇数位两个集合,每一集合搜索出满足对应集合条件的数字,而满足原集合条件的数字可由两个集合的数字相乘得到。根据单调性,可用双指针在线性时间内求出\(x\)内符合原集合条件的数字个数。

时间复杂度:\(O(log(10^{18})*10^6)\)

posted @ 2018-01-06 22:54  GerynOhenz  阅读(444)  评论(0编辑  收藏  举报