赌博不可取,我们写个程序得了

116 阅读2分钟

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战」。

前言

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

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

选出任一 x,满足 0 < x < N 且 N % x == 0 。 用 N - x 替换黑板上的数字 N 。 如果玩家无法执行这些操作,就会输掉游戏。

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

解题思路

  • 我们可以先进行模拟,自己左手右手实操一遍就完全理解游戏的意思了。
  • 当玩家挑选一个数字后,修改后的N使得下一个玩家不能获胜,则本轮玩家获胜,否则本轮玩家失败 由例子可知,当N = 1时,解是false 则当 N = 2 时,可选的只有1,下一个N = 2- 1= 1,下一轮玩家不能获胜,所以本轮玩家获胜 当 N = 3 时,可选的只有1,下一个N = 3 - 1 = 2,下一轮玩家可以获胜,所以本轮玩家失败
public boolean divisorGame(int n){
    boolean[] f = new boolean[n + 5];
​
    f[1] = false;
    f[2] = true;
    for (int i = 3; i <= n; ++i) {
        for (int j = 1; j < i; ++j) {
            if ((i % j) == 0 && !f[i - j]) {
                f[i] = true;
                break;
            }
        }
    }
​
    return f[n];
​
}
  • 正解

在「方法一」中,我们写出了前面几项的答案,在这个过程中我们发现,\text{Alice}Alice 处在 n = kn=k 的状态时,他(她)做一步操作,必然使得 \text{Bob}Bob 处于 n = m (m < k)n=m(m<k) 的状态。因此我们只要看是否存在一个 mm 是必败的状态,那么 \text{Alice}Alice 直接执行对应的操作让当前的数字变成 mm,\text{Alice}Alice 就必胜了,如果没有任何一个是必败的状态的话,说明 \text{Alice}Alice 无论怎么进行操作,最后都会让 \text{Bob}Bob 处于必胜的状态,此时 \text{Alice}Alice 是必败的。

结合以上我们定义 f[i]f[i] 表示当前数字 ii 的时候先手是处于必胜态还是必败态,\texttt{true}true 表示先手必胜,\texttt{false}false 表示先手必败,从前往后递推,根据我们上文的分析,枚举 ii 在 (0, i)(0,i) 中 ii 的因数 jj,看是否存在 f[i-j]f[i−j] 为必败态即可。