您的位置:首页 > 其它

重邮第八届ACM大赛-决赛题解报告

2017-04-23 18:49 239 查看
列表内容

A. 果姐姐的项链

贪心、构造

长度为N的01序列一共有2N种,所以L的理论最大值为2N

当N比较小时,尝试暴力构造,找规律发现:

答案具有000…0……111…1的形式(N个0+中间部分+N个1)

尝试贪心构造:

初始化序列为11…100…0(N个1+N个0),并标记其中已经出现过的序列

尝试在末尾加0,若新组成的序列(当前序列的后N-1个字符+0)未出现,则确定加0,并标记该序列出现过。若出现过,则再尝试在末尾加1。

当序列无论加0加1都无法构成未出现过的序列时(长度达到理论上限时),停止

例如,N=3时

初始化序列为111000,vis表:000、100、110、111

尝试加0,新组成000,在vis表中

尝试加1,新组成001,不在vis表中

当前序列1110001,vis表:000、100、110、111、001

尝试加0,新组成010,不在vis表中

当前序列11100010,vis表:000、100、110、000、001、010

尝试加0,新组成100,在vis表中

尝试加1,新组成101,不在vis表中

当前序列111000101,vis表:000、100、110、000、001、010、101

此时可以发现,序列长度已经超过23=8,并且此时无论加0加1肯定也都无法组成新序列了。

当前序列长度为9?那是因为没有考虑到这是循环串。

事实上若去掉最后加的1,此时的序列为11100010,刚好满足条件,其最小表示为00010111

这个序列长度首先达到了理论最大值,并且由于贪心构造,字典序也得以保证。

用同样的构造方式,容易验证,对于n≤20,都可以得到长度L=2n的序列

长度为n的01串可以当成0∼2n−1的2进制数,可以用数组简单的实现vis表。

code

B. 切披萨

二分

设切的位置为x,f(x)表示左边pizza的美味度,易知f(x)为单调函数

现在想求x1∈[0,n],使得f(x1)=f(n)2

使用二分法求x1即可

其中f(x),可以在O(n)内算出。只需要枚举每个圆与竖线的位置关系,在左边则全部加上,相交则求左部的面积。

code

C. 稳定排序

签到题

不难想到,稳定排序的结果是唯一

自己做一次稳定排序,导出p数组,然后再与给的p数组比较即可

code

D. 方程式配平

高斯消元+分数类

设每个反应物、生成物前的系数为xi,根据质量守恒定律,对每一个元素建立一个线性方程,则得到了一个关于x的线性齐次方程组Ax=0。使用高斯消元解即可。

例如:

设x1H2+x2O2=x3H2O



{2x1−2x3=0(对H)2x2−x3=0(对O)

容易发现该方程组有一个自由变元,即有无穷组解。

但在所有系数的最大公因数为1的情形下,有唯一解。

解得

⎧⎩⎨⎪⎪x1=2x2=1x3=2

事实上,输入保证有唯一解,就说明,自由变元有且只有一个,而且其它变量都是这个变元的倍数。

根据这一点,使用完高斯消元后,将自由变元置为1,倒推出其他所有变量的值。此处需要使用分数类。最后通分,化所有系数为最简整数比。

code

E. The product is k

动态规划

设f[i][j]表示a1∼ai中乘积为j的非空子序列个数,则状态转移方程为:

f[i][j]=f[i−1][j]+∑ai|jf[i−1][jai]

边界条件为:

f[0][j]={1 (j=1)0 (j≠1)

第一维i只与i-1有关,所以可以滚动优化掉

第二维j虽然大,但是有效状态只有k的因子,是k√ 级别的,可以预处理出k的因子然后离散化,也可以直接用map

code

F. js的LED屏幕

RMQ

先考虑:如果确定行数后,可以check可行性吗?

当然是可以的。假定行数为row,那么第一列占用max{a1∼arow},第二列占用max{arow+1∼a2∗row}…最后再考虑列间空格,就可以算出占用的最大宽度。

check一次row的可行性可以轻松做到O(n)的复杂度。

于是我们想到二分row

蓝儿。。蓝儿。。WA了

考虑这组数据:

15 14

3 3 3 3 3 4 4 4 4 4 5 5 5 5 5

二分做法的流程为:

l = 1, r = 15, mid = (1+15)/2 = 8

check(8):

3 4

3 4

3 5

3 5

3 5

4 5

4 5

4

宽度为4 + 5+ 1 = 10 < 14

于是l = 1, r = 7, mid = (1+7)/2 = 4

check(4):

3 3 4 5

3 4 4 5

3 4 5 5

3 4 5

宽度为3 + 4 + 5 + 5 + 3 = 20 > 14

于是l = 5 , r = 7, mid = (5+7)/2 = 6

check(6):

3 4 5

3 4 5

3 4 5

3 4

3 5

4 5

宽度为4 + 5 + 5 + 2 = 16 > 14

于是l = 7, r = 7, mid = 7

check(7):当然也不行

最终得到答案8

然而容易发现答案是5

说明,这个题目并不满足二分的条件——单调性,即并不是说只要row = i可行,那row>i就都可行

所以正确的做法是,check每一种row的值(1~n)

当然此时就无法使用O(n)的RMQ方法了

考虑使用线段树或者Sparse-Table算法

可以计算出,使用上述方法需要的RMQ次数为:

O(n1+n2+...+nn)=O(nlogn)

若使用ST算法,则O(nlogn)预处理后,O(1)回答RMQ,总时间复杂度O(nlogn),空间复杂度O(nlogn)

若使用线段树,O(n)预处理后,O(logn)回答RMQ,总时间复杂度O(nlog2n),空间复杂度O(n)

这里丧病了一波,n=2∗106,同时卡了线段树(TLE)和普通的ST(MLE)

回忆ST算法,f[i][j]表示min{aj∼aj+2i−1},f[i][j]=min{f[i−1][j],f[i−1][j+2i−1}

可以发现i只与i-1有关,所以可以滚动。

当前这一轮i可以回答满足2i≤r−l+1≤2i+1的RMQ(l,r)

所以做法就出来了。从小到大枚举row,若当前这一轮ST无法满足查询需要(即row>2i+1),则递推下一轮ST。这样就把空间复杂度优化为O(n)了

code

当然这里zkw线段树+一点简单的优化也可以过(owj)

G. The 24 Game

搜索

递归生成所有方案

最后判断时注意浮点误差

code

H. 马

数学



简单的画一个图可以发现,可以到达的点是很有规律的。

设左下角坐标为(0,0),则每次跳后,横纵坐标之和增加3。所以能够到达的点的横纵坐标之和一定是3的倍数。

容易发现,这事实上就是一个杨辉三角。横纵坐标之和反应了该点所在的行,横纵坐标之差反应了这是该行的第几个。且满足三角形递推式Cmn=Cm−1n−1+Cmn−1

接下来的任务变成了求组合数,初赛中已经介绍过了。

code

I. 魔王剑术

哈夫曼编码

编码方式显然是哈夫曼编码

一共有4n种字符串,n=20时,420=1099511627776≈1012

但实际上,对于ABCD四种字符个数都相等的字符串,他们出现的概率是一样的,所以在合并的时候可以批量合并。可以用优先队列维护二元组(p,cnt),在合并的时候:

若top的cnt>1,则将偶数部分批量合并 (p∗2,cnt2),若有单个的,再重新入队(p,1)

若top的cnt=1,则再取p第二小的出来合并,入队(p1+p2,1)和(p2,cnt2−1)

三重循环枚举A、B、C的数量(D的数量为n-A-B-C),利用乘法原理和除法原理,可以预处理出所有的(p,cnt)二元组。可以发现,当n=20时,二元组的数量只有1771个,时间复杂度完全可以接受

期望编码长度在合并的过程中可以顺便计算

code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm