1 条题解
-
0
自动搬运
来自洛谷,原作者为

pocafup
路 是人走出来的搬运于
2025-08-24 22:29:23,当前版本为作者最后更新于2021-02-07 17:12:06,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
P0:题外话
这题的原身是不存在博弈的,仅仅是给一个开局,问是否能够操作使得最后只剩两个棋子。但是我觉得博弈可做,于是在群上发了问,结果被神仙
/user/101800然后还是第一次有人帮我做数据,验题和推广,之前出的题基本上都是我自己出自己验的,果然有神仙在团内就是不一样/cy
P1:基础观察
首先需要证明两个结论
- 如果当前局面下红方可以操作,那么黑方必然也可以,反之亦然。
证明:一个可操作的局面仅有以下几种可能。
() 100 () () 001 () () 011 () () 110 ()其中 () 表示任意数量的棋子。
可以发现,在这四种状态下红黑双方均能行动,故命题得证。
由此引出下一个结论:
- 如果当前局面可操作,那么选择操作严格不劣于不操作。
证明:
由于每个操作都只会改变减少对方棋子的数量,而若一方能操作另一方也能操作,那么可以得出若一方不操作,让另一方操作只会减少自己的棋子数量,且不会影响对方之后的操作。故命题得证
P2:题解
对于 的数据,出题人良心的给了不会博弈论手动模拟的同学分数,手动模拟后打表输出即可。
对于 的数据,考虑爆搜。
暴力 dfs 寻找每一种可能。假设在某个状态下由红方行动,而他的操作会使黑方必败,则红方有必胜策略。若有平局状态,则红方可以选择平局 ,否则当前状态红方必败。(黑方同理)
暴力复杂度 ,足够通过。
对于 的数据,考虑状压打表。
思路跟dfs一样,只不过用二进制记录状态, 打表后 询问,足以通过。
接下来开始讲正解思路
由于之前证明的结论,我们可以得出,若红方初始棋子数量大于黑方,那么红方必胜。
同理,若红方初始棋子数量小于黑方棋子-1,那么红方必败。
现在仅有两种情况需要讨论:
- 红棋数量=黑棋数量
- 红棋数量=黑棋数量-1
首先讨论第一种情况:
通过基础观察,我们可以发现若红棋数量=黑棋数量,红棋只可能胜利或者平局。红棋胜利的可能仅有一个:当某一步红棋走完后,黑棋无法再次行动。
考虑什么时候会出现这种情况: 定义 () 集合为一组数字出现任意次数,例如
(101)可能为101101,也可能是空集。 对于一个不能动的情况,由于红棋数量大于黑棋,故最后局面必然是(10)1这一种情况。发现仅有两种情况能够转移得到这种情况:
(10)1100(01)(10)0011(01)由于这两种状态仅仅是
01的位置反了过来,故我们可以认为他们等价,下面仅对第一种情况进行讨论。继续考虑,发现仅有以下几种情况能得到上述情况:
(10)11100(01)(10)11001(01)(10)10110(01)由于初始棋子数量相等,而括号内棋子数量也平衡。根据初始证明,可以得出在出现这种状况时必然轮到黑方操作。
可以发现,对于上述每一种状态,黑棋必然能够使用最佳策略避开必输局面。故如果在这种情况下轮到黑方操作,双方必然平手。
对于这种情况,红方仅有一种赢的可能:当
(10)1100(01)或(10)0011(01)为初始局面。结论:如果初始局面可以通过一次转移为不可操作局面,则红方必胜,否则必然平手。
接下来讨论第二种情况:
若红棋数量=黑棋数量-1,如果对上面的证明进行分析,那么我们可以发现此时红方的处境等价于黑方的处境。
结论:若初始局面为可操作局面,则必然平局,否则红方必败。
正解证明完成,开始讨论做法
对于 的数据,考虑在红棋=黑棋时暴力枚举每个位置进行操作后判断是否为不可动局面,复杂度
由于出题人不确定有没有 做法,而其他做法的复杂度显然过不去这个,故 只开到了 。
对于 的数据,考虑暴力上随机化。
发现若有一个位置能够使得变化和局面可操作,则继续判断无意义。
故对于红棋=黑棋时仍然暴力枚举,但是枚举时随机跳位置检索是否不可操作。
复杂度不太会证,但实际效果优秀,可以过 的数据。
对于 的数据,考虑移动一步后出现平局的可能状态。
上面已经讲过,仅存在
(10)0011(01)和(10)1100(01)两种可能。故我们可以判断数组是否为这种情况,具体写法将在代码中给出。复杂度 )
const int MAXN = 1e7+5; const int MAXM = 1e5+5; const int mod = 1e9+7; int dx[4] = {1,0,-1,0}, dy[4] = {0,1,0,-1}; int n,m,t,pos[MAXN],k,a,b,c,red,black; inline void case1(){ int pivot = 0,ab = 0; For(i,1,n-1) if(pos[i]==pos[i+1]) { if (pivot && pos[i]==1) {puts("TIE");return;} else if (pos[i]==1) pivot = i; if (pos[i]==0) ab++; } if (!pivot) {puts("TIE");return;} if ((pivot == 3 && pos[1] == pos[2]) || (pivot == n-3 && pos[n-1] == pos[n])) {puts("WIN");return;} if (ab == 2 && ((pivot > 3 && !pos[pivot-1] && !pos[pivot-2] && !pos[pivot-3]) || (pivot<=n-4 && !pos[pivot+2] &&!pos[pivot+3] && !pos[pivot+4]))) {puts("WIN");return;} puts("TIE"); } inline void case2(){ For(i,1,n-1) if (pos[i]==pos[i+1]) {puts("TIE");return;} puts("LOSE"); } signed main(){ t = read();pos[0] = -1; while(t--){ n = read();pos[n+1] = pos[n+2] = pos[n+3] = -1; red = 0; For(i,1,n) pos[i] = (get()=='1'),red+=(pos[i]==1); black = n-red; if (red>black) puts("WIN"); else if (red<=black-2) puts("LOSE"); else if (red==black) case1(); else case2(); } }
- 1
信息
- ID
- 6278
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者