虽然已经过去了很久,而且我也没写补题的代码(咕咕咕&写了不知道交到哪里),但是感觉这场比赛的题目质量还是不错的,还是写一下题解
C:
大致题意:
定义一个序列a1,a2,...ana_1,a_2,...a_na1,a2,...an的价值value(a)∑i=1nai∗1000n−ivalue(a)\sum_{i=1}^n a_i*1000^{n-i}value(a)∑i=1nai∗1000n−i
给一个长nnn的序列AAA,长mmm的序列BBB,在AAA中挑一个子序列A′A'A′,BBB中挑一个子序列B′B'B′,求有多少个本质不同的方案满足value(A′)>value(B′)value(A')>value(B')value(A′)>value(B′),其中两个子序列不同当且仅当价值不同
n<=5000,1<=Ai,Bi<=100n<=5000, 1<=A_i,B_i<=100n<=5000,1<=Ai,Bi<=100
先考虑怎么选子序列使得不选重。假设A1′,A2′...An′A'_1,A'_2...A'_nA1′,A2′...An′的值已经定了,那么从AAA序列的开头开始,每次找当前位置后面Ai′A'_iAi′第一次出现的位置作为选择的位置,这样可以保证选出来的序列不重复。
将上述选法转化为dp方法,比如说我们现在在AAA里面dp,设f[i]f[i]f[i]表示以iii为结尾的子序列有多少个,那么设从1到iii,A[i]A[i]A[i]上一次出现的位置是last[i]last[i]last[i],可以得到dp转移式f[i]=∑j=last[i]if[j]f[i]=\sum_{j=last[i]}^{i}f[j]f[i]=∑j=last[i]if[j]
考虑A′A'A′和B′B'B′的价值比较,因为序列每个元素都不超过100,所以其实是先比较长度,再按位比较。
那么将value(A′)>value(B′)value(A')>value(B')value(A′)>value(B′)情况分为两种
1.A′A'A′的长度大于B′B'B′
这种情况可以对A,BA,BA,B两个序列算出每个长度有多少个子序列(这个可以在上面那个dp那里加一维长度解决),前缀和一下就行了。
这部分O(n2+m2)O(n^2 + m^2)O(n2+m2)
2.长度相等
设g[i][j][0/1]g[i][j][0/1]g[i][j][0/1]表示当前A′A'A′序列结尾是AiA_iAi,B′B'B′序列结尾是BiB_iBi,A′A'A′的价值是否已经大于B′B'B′,的方案数,也是可以用二维前缀和优化的
这部分O(nm)O(nm)O(nm)
E
一个n*m的网格图,有的位置有障碍,有k(k<=m)个机器人从第一行上方竖直向下走进入图,你可以在没有障碍的位置放转向器使机器人转弯,但一旦放了就只能从这个转向器提供的这两个方向进入,最后一行有h(h<=m)个位置往下走就是出口,问能否放一些转向器使每个机器人最终都能走到出口
我觉得题解写的很好,不如直接贴题解了(懒)

G
一个显然的性质是只有当别的棋子对拿不了了我才会只拿一个棋子(该棋子左下角没有其它棋子又不能和白棋子一起拿而且卡住了别的棋子对)
所以任何时候剩余的棋子状态都可以用一条从左上到右下每次只能向下或向右的分界线表示。于是我们可以用C2nnC_{2n}^nC2nn的状态表示这个分界线。
我们假设二进制状态中0是向右,1是向下,发现拿掉一个棋子的操作对这个状态的改动是把一个‘10‘变成’01‘。
然后就直接dp
O(C2nnn2)O(C_{2n}^{n}n^2)O(C2nnn2)
K
首先,如果由某个叶子节点它的父亲出度>1,那么先手必胜
证明:
设原状态是X
1.如果拿掉这个叶子节点是必败态,X是必胜态
2.如果拿掉这个叶子节点是必胜态A,那么A一定能转移到某个必败态B,且因为拿掉这个叶子后并没有产生新的叶子,所以A能转移到的状态X也能转移到,因此X也能转移到必败态B,于是X是必胜态
如果不存在这样的叶子,那么统计每个叶子向根走到第一个出度>1的祖先的距离
如果距离全为偶数,那么先手必败
否则先手必胜
策略是每次将所有奇数的拿掉叶子变成偶数
正确性显然?
嗯暂时写这么多。

本文解析了一场编程比赛中的三道题目:C题涉及序列价值计算与子序列选取策略;E题探讨网格图中机器人路径规划及转向器放置问题;G题通过动态规划解决特殊棋盘游戏中棋子拿取策略。

853

被折叠的 条评论
为什么被折叠?



