ACM一些题目

Low Power

先二分答案,可以通过调整证明同一台机器选的两个芯片必然是提供能量数值相邻的两个。所以再贪心一下就可以了。

时间复杂度\(O(n \log n)\)。

Factors

假设\(k\)可以写成\(\prod p_i^{q_i}\),由于\(k\)要尽可能小,所以\(p_i\)是最小的几个质数,\(q_i\)递减。决定\(f(k)\)的值的,只与\(q_i\)有关,所以我们可以暴力出各个\(q_i\)的取值,由于\(k<2^{63}\),所以方案应该是很小的,好像只有\(10^4\)个,也就是说,不同的询问只有\(10^4\)个。所以我们可以预处理出所有的询问的答案。

时间复杂度\(O(10^4 + Q)\)。

Magical GCD

首先枚举区间的左端点\(L\)。

如果我们再次枚举右端点,我们可以发现一个问题:区间\([L,R+1]\)的\(gcd\)要么等于\([L,R]\)的\(gcd\),要么小于\([L,R]\)的\(gcd/2\),也就是说,\(gcd\)的值最多改变\(log 10^{12}\)次,即我们需要枚举的\(R\)的取值只有\(log 10^{12}\)个。所以我们使用二分来找到我们需要的\(R\)的取值。区间\(gcd\)可以使用RMQ。

时间复杂度\(O(n \log n \log 10^{12})\)。

unix纪元

考你会不会编程。不过网上的代码我见都是用time_t,可惜我不会。

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

Zhu's multiset

怎么提交?

先二分答案,然后用个优先队列贪心。

时间复杂度\(O(n\log n \log 10^6)\),极有可能超时,囧。

Team Them Up!

如果两个人不认识,就将他们连一条边。然后就有若干个二分图,DP一下分配方案就好了。

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

感觉这题的重点是连边的方式,如果考虑选完全图的话,难度就很大了(反正我是不会做的)。

Boatherds

先算出所有点到根的距离,记为\(dep_v\),那么题目求的是,是否存在一个\(v\)和一个\(u\),使得\(dep_v+dep_u-2dep_{lca}=k\),\(k\)是题目求的路径长度,\(lca\)是这两个点的最近公共祖先。

我们可以采用启发式合并,每个点记一个set,表示该子树含有的\(dep\)。对于一个点\(v\),要把它和它的所有孩子合并成一个set。现在考虑将\(A,B(|A|<|B|)\)合并,逐一枚举\(B\)里的元素\(x\),对于一个询问\(k\),如果\(A\)存在元素\(k+2dep_v-x\)的话,就说明有一条经过点\(v\)的路径的长度为\(k\)。

时间复杂度\(O(n \log^2 n m)\)。

看到网上的一般做法是树分治,其中看到有一个很神奇的东西:给出一堆数,求从中选两个数,使得它们的和为\(k\)的方案数。

如果暴力采用set之类的数据结构,是可以轻松做到\(O(n\log n)\)的,但是还有一个神奇做法:

方便起见,假设所有的数两两不相等,采用下面的算法:

l = 0, r = n - 1
while l < r
if al + ar > k
r = r - 1
if al + ar < k
l = l + 1
if al + ar == k
get a solution
l = l + 1

在\(O(n)\)的时间内可以完成。正确性是很显然的。

连环锁

原来这个根格雷码有关,但是如果不知道这个应该怎么办呢?

这里是我了解到的东西:

  • 可以发现,连环锁每一个状态(除了000...00和100...000)都能转移到其他的两个状态,如果把状态变成点,转移变成边,那么就可以知道这一条链。格雷码就按顺序给这些状态编号。
  • 格雷码与二进制之间的转移方式与异或相关:比如格雷码的第\(i\)位(\(1\)是最高位)等于其对应二进制数前\(i\)位(包括第\(i\)位)的异或值。

所以,解决这题的话,把格雷码转成二进制再变成十进制后相减就是答案了。

时间复杂度\(O(n^2)\)(需要高精度)。

Quad Tiling

裸题,直接使用矩阵乘法。

Garden

这题差不多所有人都做出来了,就我QAQ.

注意到\(k\)是固定的,也就是说任何时候,可以照相的区间个数是\(n-k+1\),我们维护这些区间和的最大值就可以了。

One-move checkmate

模拟即可,和棋不算将死!这里的和棋指黑国王可以不动。

ATP

二分答案,然后把竞赛的那棵完全二叉树贪心出来,注意要使用BFS,因为厉害的选手越靠近树的根就能够消灭更多的对手。

Word Rings

学习到了一种快速判负环的方法!

bool circle(u)
mark[u] = true
for any e(u,v)
if relax(u->v)
if circle(v) return true
mark[v] = false
return false
上一篇:浙江工商大学15年校赛I题 Inversion 【归并排序求逆序对】


下一篇:47、求1+2+3+...+n