除数博弈

标签: 脑筋急转弯 数学 动态规划 博弈

难度: Easy

爱丽丝和鲍勃一起玩游戏,他们轮流行动。爱丽丝先手开局。

最初,黑板上有一个数字 n 。在每个玩家的回合,玩家需要执行以下操作:

  • 选出任一 x,满足 0 < x < n 且 n % x == 0 。
  • n - x 替换黑板上的数字 n

如果玩家无法执行这些操作,就会输掉游戏。

只有在爱丽丝在游戏中取得胜利时才返回 true 。假设两个玩家都以最佳状态参与游戏。

示例 1:

输入:n = 2
输出:true
解释:爱丽丝选择 1,鲍勃无法进行操作。

示例 2:

输入:n = 3
输出:false
解释:爱丽丝选择 1,鲍勃也选择 1,然后爱丽丝无法进行操作。

提示:

  • 1 <= n <= 1000

Submission

运行时间: 24 ms

内存: 15.9 MB

import math
class Solution:
    def divisorGame(self, n: int) -> bool:
        return n%2 == 0

Explain

题解的核心思路基于数学归纳法,观察到一个简单的模式:当初始数字 n 是偶数时,爱丽丝会赢;当 n 是奇数时,爱丽丝会输。这是因为从偶数开始,爱丽丝可以通过选择 x = 1 使得鲍勃面对的数字变为奇数。奇数的任何除数(除了 1)也是奇数,因此鲍勃操作后的结果仍然是偶数,轮回到爱丽丝时她面对的又是偶数。这样爱丽丝可以保持在她的每个回合都将数字变为奇数,而鲍勃只能将数字变回偶数,直到数字减少到 2,爱丽丝赢得比赛。当 n 是奇数时,爱丽丝第一个操作会将其变为偶数,之后鲍勃可以应用相同的策略。

时间复杂度: O(1)

空间复杂度: O(1)

import math
class Solution:
    def divisorGame(self, n: int) -> bool:
        # 根据n的奇偶性返回结果,如果n是偶数,爱丽丝获胜,返回True;如果n是奇数,爱丽丝失败,返回False
        return n % 2 == 0

Explore

在除数博弈中,选择 x = 1 是因为这是最简单且总是可行的选择,它能将偶数减少到最接近的奇数,使得鲍勃在接下来的回合面对的是奇数。选择除 1 以外的 x(必须是原数的因子且小于原数),如选择 x = 2 或更高的偶数因子,也会使结果变为一个较小的偶数,这样在下一个回合中爱丽丝仍然可以利用相同的策略。然而,选择 x = 1 更为直接且保守,因为它保持了游戏的简单性和策略的明确性。选择更大的 x 可能会导致游戏提前结束,但这通常不会改变最终的胜负结果,因为关键在于奇偶转换的控制。

在除数博弈的规则下,没有特殊的 n 值使得基于奇偶性的策略无效。这种策略的有效性是由游戏的基本规则决定的,即玩家必须选择一个当前数字的因子作为 x,且这个因子必须小于当前数字。偶数与奇数的特性决定了其因子的奇偶性,从而影响了游戏的结果。无论 n 的具体值如何,只要它是偶数,爱丽丝总是可以通过选择 x = 1 来保持优势;如果是奇数,她将失去这一优势。因此,这种策略在所有 n 值上都是有效的。

当 n 是奇数时,爱丽丝选择 x = 1 会将 n 变为偶数,这是因为从奇数减去 1 会得到偶数,从而尝试改变游戏的局面。选择 x = 1 是一种简单且直接的策略,因为它确保了数字的最大减少并快速改变数字的奇偶性。在这个游戏中,最优的策略通常是尽可能长时间地控制游戏的进程,而将数字维持在偶数是爱丽丝的最佳策略,因此在奇数的情况下选择 x = 1 是最优的,尽管它不保证爱丽丝能赢(如果 n 初始就是奇数)。