力扣一日一练(38)——除数博弈

172 阅读1分钟

题目:除数博弈

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

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

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

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


示例

示例 1:

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

示例 2:

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

提示:

  • 1 <= N <= 1000

使用JavaScript语言

/**
 * @param {number} N
 * @return {boolean}
 */
var divisorGame = function(N) {
    var dp = [];

    dp[1] = false;  //N==1时必输
    dp[2] = true;  //N==2时必胜

    for(var i = 3; i <= N;i++){
        dp[i] = false;
        for(var j = 1;j < i;j++){
            if((dp[i-j]==false)&&(i%j == 0)){ //若j是i的余数且dp[i-j]为假(0)的话,则代表当前为真(1)
                dp[i] = true;
                break;  //只要出现一次就可以
            }
        }
    }
    // console.log(dp[N])
    return dp[N]
};

分析

归纳法:

  1. 最终结果应该是占到 2 的赢,占到 1 的输;
  2. 若当前为奇数,奇数的约数只能是奇数或者 1,因此下一个一定是偶数;
  3. 若当前为偶数, 偶数的约数可以是奇数可以是偶数也可以是 1,因此直接减 1,则下一个是奇数;
  4. 因此,奇则输,偶则赢。

动态规划:

  1. 将所有的小于等于 N 的解都找出来,基于前面的,递推后面的。
  2. 状态转移: 如果 i 的约数里面有存在为 False 的(即输掉的情况),则当前 i 应为 True;如果没有,则为 False。
  3. n=3之后,先走的如果想赢(爱丽丝如果想赢),就需要找到小于n的数k,能使得在符合条件(n%k==0)的基础上还能让n-k(下一局的n)是先走输。(即n-k的最优解是输,即下一局的人再怎么聪明也是输。)
  4. 即在内层循环中如果找到一个数使得if((dp[i-j]==false)&&(i%j==0)),那么该数是先走赢,一层循环走下来找不到这么一个数的话,那么该数是先走输。故只要找到一个符合条件就可以直接跳出循环了。

 

题目链接

leetcode-cn.com/problems/di…