[LeetCode] 1025. Divisor Game

Description

Alice and Bob take turns playing a game, with Alice starting first.

Initially, there is a number N on the chalkboard. On each player's turn, that player makes a move consisting of:

  • Choosing any x with 0 < x < N and N % x == 0.
  • Replacing the number N on the chalkboard with N - x.
    Also, if a player cannot make a move, they lose the game.

Return True if and only if Alice wins the game, assuming both players play optimally.

Example 1:

Input: 2
Output: true
Explanation: Alice chooses 1, and Bob has no more moves.

Example 2:

Input: 3
Output: false
Explanation: Alice chooses 1, Bob chooses 1, and Alice has no more moves.

Note:

  1. 1 <= N <= 1000

Analyse

黑板上有个整数N,每个人都作如下两个操作

  • 选择一个整数xx 满足 0 < x < NN % x == 0
  • N 变成 N - x

无法选择出满足条件的整数x时输

Alice先手

两个人作出的选择都是最优的

动态规划

  • 定义dp[i] 为当N为i,且轮到Alice选择时是否会胜利

  • 找出递推关系

dp[i] = true    ## 存在x,满足(dp[i - x] == false) && (N % x == 0) && (1 < x < N)
        false   ## 其他

给出初值

dp[0] = false

dp[1] = true

最终代码

bool divisorGame(int N) {
    bool dp[N+1] = {false}; // 用false初始化为长度为N+1的dp数组

    for (int i = 2; i <= N; i++) {
        for (int x = 1; x < i; x++) {
            if (i % x == 0) {   // N % x == 0 ?
                dp[i] = dp[i] || !dp[i-x];  // dp[i - x] == false ?
            }
        }
    }

    return dp[N];
}

找规律

对这道题来说,只有N一个输入,且N定义的是dp的长度,dp的值对于所有的N来说都是一样的,可以先手动算几个,这里计算N=6

N 1 2 3 4 5 6
结果 x x x

N=2时,Alice选择x=1,胜

N=3时,Alice选择x=1,败

N=4时,Alice选择x=1,Bob面对N=3的情况,Alice胜,这里Alice如果选择2的话就输了(但题目说玩家做出的选择都是最优的)

N=5时,Alice选择x=1,Bob面对N=4的情况,Bob胜,Alice败

N=6时,Alice选择x=1,Bob面对N=5的情况,Bob败,Alice胜

看出规律,只要轮到Alice的时候N是偶数,Alice就赢定了

用位运算 (N & 1) == 0 来判断奇偶

bool divisorGame(int N) {
    return (N & 1) == 0;
}

简单的证明

  • 谁拿1谁就输

  • N为奇数时,Alice必输
    奇数的因子也是奇的,无论Alice选什么,剩下的N-x为偶数,x < N,N-x至少为2,Bob再选1,N-x又变成了奇数,重复这个操作,最后Alice会拿到1

  • N为偶数时,Alice必胜
    Alice每次选1,Bob就拿到了奇数,Alice胜

References

  1. Proof of returning N % 2 == 0
posted @ 2020-01-13 19:37  arcsinW  阅读(273)  评论(0编辑  收藏  举报