[CF919F] A Game With Numbers 题解
这里带来一个跑得很快而且写起来也相对简单的做法。
首先考虑这种题一看就是博弈论,主要就是一个性质——能走到必败态的都是必胜态,只能走到必胜态的才是必败态。
那么就很显然了,从终止状态反向推,先看看状态数,一个人的手牌只有八张五种,所以最多只有 \(495\) 种状态,那么两个人的手牌加起来也不过只有约 \(2.5\times10^5\) 种状态。
考虑先将这些状态编上号,建立双射,方便之后的转移,然后考虑做转移,设 \(f_{i,j}\) 表示先手的状态编号为 \(i\),后手状态编号为 \(j\) 的态势。
考虑怎么转移,首先初始状态,假设手牌全是 \(0\) 的状态编号为 \(0\),则 \(f_{0,i}=1\),\(f_{i,0}=0\),且 \(f_{i,0}\) 可以作为状态转移别人,而 \(f_{0,i}\) 不行,因为我们是反向转移,所以当前的先手如果已经赢了的话,上一步后手就根本无法操作。
现在考虑如何转移,一个点肯定是倒推上一个状态,所以肯定是当前后手的一个数减去当前先手的一个非零数得到上个状态的原数,如果该状态是必败态,则转移的就是必胜态,如果该状态是必胜态,则转移到必败态,但是不是一定转移,而是只有确定这个点正向能转移到的点都是必胜态,这个点才是必败态。
一个点能转移多少点呢?考虑手里任意一种非零牌跟对手的每种非零牌都可以匹配进行操作,所以就可以快速得到转移种类,注意这里一模一样的牌就算有多张,匹配转移也只能算一种。
最后查询就直接调用查询就好了,代码比较简单。