2015 暑假集训14级第一周周赛解题报告

A.小模拟题
根据要求模拟即可。没什么可讲的。。
参考代码:http://paste.ubuntu.com/11978075/

B.组合计数
首先排序,然后可以在O(n)复杂度内求出每个hero所能拿的sword的最大范围。
然后可以从第一个开始拿,考虑对于当前第i个hero来说,假设第i个hero最多能拿到第j个sword,那么首先这j个中一定有i-1个已经被前i-1个拿到了,所以第i个只能从后面的剩下的j-i个中选,于是可以拿j-i个。然后用高中学到的组合数学的知识,将每一个的可选个数乘起来即可。
本题时间复杂度也是两次排序的复杂度,O(n*logn)。
参考代码:http://paste.ubuntu.com/11978123/

C.最大公约数
这题高中的积分知识就足够了。。然后加上个最大公约数就可以解决这题了。
参考代码:http://paste.ubuntu.com/11978143/

D.DP
首先,需要注意到,如果x可以整除y,y可以整除z,那么x一定可以整除z。于是本题可以转化成最简单的最长上升子序列的模型(仔细想想为什么)。
然而最长上升子序列的复杂度是O(n^2)的。所以剩下再考虑时间复杂度问题。对于这题来说,数字大小最多只有10^6,所以可以哈希一下,然后利用枚举倍数的方法。只从每个数的倍数中进行枚举。枚举倍数的复杂度是一个调和级数,即O(n/1+n/2+n/3+…+n/n)≈O(n*logn)对于10^6的数据规模已经足够。
参考代码:http://paste.ubuntu.com/11978177/

E.博弈论
这题可以找规律做出来。在这里给一个可以推出来的方法。
首先需要知道两个定义:必胜态和必败态。均指在当前的状态下先手必胜或者必败。
然后有两个定理:1.必胜态的下一步一定有一个是必败态。2.必败态的下一步一定全是必胜态。(仔细思考一下这两句话,这两句话是解决所有此类博弈论的基础)
然后,这题已知必败态是左下角,其他均未知。然后就可以根据那两个定理来不断的推出来。由于空间限制,,,直观图可以看这篇博客。传送门:http://blog.csdn.net/scf0920/article/details/39273327
参考代码:http://paste.ubuntu.com/11978223/

F.。。。
这题是2013年的成都邀请赛现场的签到题。。数据是不可能有坑的。。理解好题意,处理好几个细节就很简单了。
要注意到如果后面全报对的话,那么出错的肯定是第一个。还有出错的那个的后面的是根据出错的那个报的。报错的那个并不一定是把数字报大了。。
参考代码:http://paste.ubuntu.com/11978296/

G.优先队列+贪心
首先根据题意中的两个人的要求,可以贪心的去取,由于一个要拿大的,一个要拿小的,可以用两个优先队列来维护,然后每次取了之后,就要看一下取了这个之后,他所影响到的那些方块的状态是否已经处于可以被取走的状态,可以的话,就加入到优先队列中进行维护。然后由于坐标太大,普通哈希没法存储,可以用map来存储。然后剩下的就是不断的模拟这个过程直到全部被取完。
时间复杂度为O(n*logn)。
参考代码:http://paste.ubuntu.com/11978324/

H.字典树+并查集+欧拉回路
这题虽然用到了三个算法,但是其实并不难,三个算法是分别独立出现的。最后一个欧拉回路只需要用到一个知识:如果可以连起来的话,那么只要满足最多只有两个点的度数为奇数就可以。这个完全可以自己推出来。推算过程:中间的每个连接处都是相同的颜色,只有首末两端的点是可以不同颜色的,所以如果首末两端的点颜色不同,那么就只有这两个颜色的度数为奇数,如果相同,则都为偶数,因为中间的颜色都是两两出现的。然后知道了这个之后,就可以判断一下度数是否满足这个要求就可以了。然后还有需要注意的是,图可能会不连通,即虽然度数符合,但并没法形成一个图,所以要先用并查集判断一下是否连通。然后再考虑时间复杂度的问题。字符串太多,一个个的比对必定超时,可以将字符串转到字典树中。复杂度就降为所有字符的个数了。由于题目中说字符个数不超过80W,所以这个时间复杂度是足够的。不想重新写一遍代码了。。直接复制的第一次做的时候的代码,所以代码略挫。。见谅。。
参考代码:http://paste.ubuntu.com/11978375/

I.。。。。。
暴力找6种情况的最大值。。不多说了。。WA的童鞋再仔细想一下缺哪几种情况。。
参考代码:略。

J.思维题
这里n*logn的方法是过不去的。只能用O(n)的方法。方法有很多。最简单的一种是标记一下端点的状态。
这题的大体做法是先预处理出所有点上的总伤害预处理出来。然后O(1)的判断每个怪是否被杀掉。
预处理的过程中,标记一下每个端点的状态,比如将(左端点)加上伤害值,(右端点+1)减去伤害值,然后再遍历一遍,遍历过程中求出前缀和然后存起来。然后就可以查询的时候只需要判断一下血量值是否小于伤害值即可。
时间复杂度O(n)。
参考代码:http://paste.ubuntu.com/11978419/

你可能感兴趣的:(ACM,周赛)