首页 > 技术文章 > 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛

GerynOhenz 2018-05-07 23:02 原文

埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛

Wasserstein Distance

题目描述:有两个序列\(a_i, b_i\),每次可以选择两个位置\(x, y\)以及一个数字\(c \leq a_x\),然后\(a_x-=c, a_y+=c\), 费用为\(c\times |x-y|\)。问将\(a\)序列变成\(b \)序列的最少花费。

solution
其实每次操作可以划分成\(|x-y|\)次相邻操作,费用是一样的,所以\(O(n)\)模拟即可出答案。

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

合约数

题目描述:给定一棵\(n\)个节点的树,并且根节点的编号为\(p\),第\(i\)个节点有属性值\(val_i\), 定义\(F(i)\): 在以\(i\)为根的子树中,属性值是\(val_i\)的合约数的节点个数。\(y\)\(x\)的合约数是指\(y\)是合数且\(y\)\(x\)的约数。小埃想知道对\(1000000007\)取模后的结果.

solution
\(dfs\),用\(map\)记住当前子树每种\(val_i\)的个数,启发式合并,对于每个节点根号枚举约数。

时间复杂度:\(O(nlogn+n\sqrt{n})\)

序列变换

题目描述:给定两个长度为\(n\)的序列,\(a_i, b_i\), 通过\(3\)种操作使得\(a_i\)变换为\(b_i\)

  1. 交换\(a_i\)\(a_j\)\(i!=j\)
    首先通过若干次的操作\(1\)\(a_i\)变换成\(c_i\)
  2. \(1\)个数乘\(2\)或者加\(1\)
  3. \(1\)个数除以\(2\)或者减\(1\),如果是奇数,则不能除以\(2\)
    \(c_i>b_i\), 则只能对\(c_i\)实施操作\(3\),若\(c_i<b_i\), 则只能对\(c_i\)实施操作\(2\)。即操作\(2, 3\)只能选一种进行若干次操作。
    \(a_i\)变成\(b_i\)的最少操作次数。

solution
穷举排列,交换次数为\(n\)减置换群个数。操作\(2\)与操作\(3\)互逆,而操作\(3\)的操作次数比较好算。

时间复杂度:\(O(n!*n*log(10^8))\)

数字游戏

题目描述\(A, B\)在玩游戏。\(A\)先从区间\([L1, R1]\)里选择\(1\)个数字\(n1\)\(B\)看到\(A\)选的数字后,从\([L2,R2]\)里选择\(1\)个数字\(n2\), 将\(n1\)\(n2\)连接在一起(\(n1\)在前, \(n2\)在后),形成一个新的数字,若这个数字可以被\(p\)整除,那么\(B\)获胜,否则\(A\)获胜。若两个人均采取最优策略,试问谁获胜?

solution
枚举\(A\)选择的数模\(p\)后的值\(x\),假设\(B\)选的数\(y\),枚举\(y\)的位数\(w\),问题变为\(x*10^w+y=0(mod p)\)是否存在\(y\),这简单判断一下即可。

时间复杂度:\(O(10^6*9)\)

小Y吃苹果

题目描述:有一个数\(X\),进行\(n\)次操作,每次操作:若\(X\)为偶数,则\(X/=2\), 否则\(X=\frac{1}{2}(X+1)\),最后\(X=1\),给定\(n\),问初始值\(X\)的可能个数。

solution
\(2^n\)

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

1+2=3?

题目描述:找出满足\((x)XOR(2x)=3x\)的第\(n\)个数。

solution
满足式子的相当于二进制左移一位与原数的\(1\)位置不重叠。
\(f[i]\)表示二进制长度为\(i\)的数中有多少个数满足式子,\(g[i]=\sum_{j=1}^{i} f[j]\)
\(f[1]=2, f[2]=1\)。因为左移一位不能与原数的\(1\)位置重叠,所以\(f[i]=g[i-2]\)
求出\(f[i], g[i]\)后就可以从最高位开始确定\(x\)的二进制表示。

时间复杂度:\(O(64)\)(每次询问)

小Y做比赛

题目描述:小Y正在和大家一起参加比赛,比赛共有N道题目,比赛规则是根据做出题目数量来确定排名的,当出题数相同则罚时少的排名在前,一位参赛选手罚时等于他每道做出的题目的罚时之和,做一道题目的罚时等于做出该题目时距离比赛开始后的时间,另外每次错误的提交也会增加罚时。
小Y很厉害,他能做出所有的N道题目,并且不会有提交错误。而对于每道题目,他需要花费一定的读题时间和做题时间,当然他需要读过一道题才能去做那道题。
小Y有一个做题习惯,就是仅当他有两道读过并且还没做出的题时,他才会去做题,并且会选择去做花费做题时间较少的那题。除了只剩一题的情况下,他会去把那题做完。
现在已知这些题目对于小Y的读题时间和做题时间,而小Y的读题顺序是任意的,求小Y最少可能的罚时。(假设小Y在任何情况下都会在比赛时间内做完所有题)

solution
设读题时间为\(read_i, write_i\)。把信息复制一遍,一组按读题+做题时间从小到大排序,另一组按读题时间排序从小到大排序。假设第一组枚举到\(x\), 第二组枚举到\(y\)。首先把第二组的第一题读了,当前读了题的是\(nid\),然后每次先找到最小的还没做的\(x, y\),若\(read_y+min(write_y, write_{nid})<read_x+write_x\),则读\(y\)题,做\(nid, y\)\(write\)较小的那一题,否则读并做\(x\)题,更新\(nid\)

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

小Y与多米诺骨牌

题目描述:小Y用一副高度不一的多米诺骨牌摆成了一排直线,一共\(n\)张骨牌,其中第\(i\)张骨牌在直线上的坐标为\(x_i\),高度为\(h_i\),任意两张骨牌的\(x\)坐标都不相同。摆完之后他发现,推倒一张骨牌并不一定能够让所有牌都连续倒下,于是他想知道最少要直接推倒多少张牌(向左向右皆可),才能让所有牌直接或间接被推倒。
骨牌的厚度不计,也就是说,比如向右(\(x\)轴正方向)推倒骨牌\(i\)时,则当骨牌\(j\)满足\(x_i<x_j<x_i+y_i\)时会被间接地向右推倒(同理,向左时需要满足\(x_i-y_i<x_j<x_i\))。

solution
先预处理出\(le[i], ri[i]\)表示向左、右推倒\(i\)时最左边倒了的编号,最右边倒了的编号。
\(f[i]\)表示推倒前\(i\)个的最少花费,并用线段树维护。若\(f[i-1]\)存在,则\(f[ri[i]]=min(f[ri[i]], f[i-1]+1)\)\(f[i]=min(f[j]+1), le[i]-1 \leq j <i\)

时间复杂度:\(O(nlogn)\)每组数据

二数

题目描述:每一位都是偶数的数称为二数,给出一个数\(x\),求与\(x\)的差的绝对值最小的二数。

solution
从最高位开始找到第一个奇数位,然后缩小放大都试一下。

时间复杂度:\(O(数字长度)\)每次询问

小Y写文章

题目描述:小Y写了一篇文章,文章共\(n\)段,对于文章的每一段小Y对它都能计算出一个估值\(A_i\),而一篇文章的不连贯值定义为\(max \begin{Bmatrix} |A_i-A_{i-1}|, 2 \leq i \leq n \end{Bmatrix}\),现在小Y想要发布他的文章,但是编辑小Z让他加入一些广告,具体来说就是\(m\)段估值分别为\(B_i\)的新段落。已知小Y加入新段落的时候不需要考虑新段落之间的顺序,但是只可以在原文章的开头段之前、结尾段之后、或两段之间加入一段新段落,每个位置只能加入最多一段。求出将这\(m\)个新段落全都加入之后的最小不连贯值。

solution
二分+上下界网络流。

时间复杂度:\(O(log(10^9)nm^2)\)

树上最大值

题目描述:一个连通无向图\(G=(V,E)\),共有\(n\)个点,\(n−1\)条边,每个点有一个权值\(a[i]\),选取集合\(A\)和集合\(B\),\(A\cap B=\phi\),使得\(A\)中的点两两形成的路径上的点,和\(B\)中的点两两联通路径上的点没有任何交集。换句话说,定义\(A',\forall u, v \in A,u, v\)简单路径上的点\(\in A'\) , 定义\(B',\forall u,v\in B,u, v\)简单路径上的点\(\in B',A'\cap B' = \phi\)。求\(A\)\(B\)的“异或和”之和的最大值,“异或和”是指集合中所包含的点的权值的异或和。

solution
一条边把点分成两部分,在这两部分选点形成\(A, B\)。树形\(dp\),异或线性基最多只有\(30\)个,所以每个节点只需记录\(30\)个数。

时间复杂度:\(O(n*30*30)\)

K序列

题目描述:给一个数组\(a\),长度为\(n\),若某个子序列中的和为\(K\) 的倍数,那么这个序列被称为“\(K\)序列”。现在要你对数组\(a\)求出最长的子序列的长度,满足这个序列是\(K\)序列。

solution
简单\(dp\).

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

推荐阅读