由于考试时不知道正确的方法,结果想出一个新的做法,送给大家借鉴一下。原来的方法见wc07
考虑每一个状态,a1~an,其中an的值对结果是没有影响的。我们把最后一位去掉,将规则改为每次从i中取出一个,并把少于3个石子放入比i大的瓶子中。我们考虑以下一个类似于sg的函数:
G(i) = 2*(n – i) – 1 (当ai为奇) 否则为 0
然后每一个状态即:xor (G(i) (1≤ii 可以得 2*(n – i) – 1<> 2*(n – j) – 1,即g(i) xor g(j)<>0,所以结果也会变成非0的。
3 f非0时,一定有操作可以使得f变为0。证明该问题只需构造一个满足条件的操作即可。我们假设f的最高位为第p位,那么一定可以找到至少一堆满足g(i) 的第p位为1,且它的石子的个数为奇数个。我们就选他作为取出石子的第一堆。取出这一堆以后,f的值会变成h = f xor g(i)。那么一定会有 hi) 使得g(j) = h 或 g(j) = h + 1。然后在j中放入一个石子。这样h将变成0或1。如果h = 0 则将最后一个石子扔到第n堆中,如果h = 1 就扔到第n-1堆中。这样就可以确保操作之后f变成 了0。
通过以上3点可知,f非0的状态可以保持不会遇到0的状态,即不会输。
由以上方案,我们可以在O(n)的时间内计算出初始状态的胜负情况。对于计算所有的走法,只要保证在走完一步以后对手面临必败态就可以了。对于给定的数据范围,可以直接枚举,也可以用组合的方法获取复杂度更低的方法。这个问题就很好地解决了。