每日一题:除数博弈

文章讨论了两位玩家轮流操作的游戏规则,玩家需选择能整除当前数字的数进行减法,先手持有奇数的爱丽丝在n为偶数时必败,可以通过动态规划求解先手是否必胜的问题。
摘要由CSDN通过智能技术生成

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

最初,黑板上有一个数字 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

数学题,先找找规律:

  • n = 1时,Alice先手,什么都做不了,失败。
  • n = 2时,Alice拿走1,Bob剩1,胜利。
  • n = 3时,Alice只能拿走1,根据n = 2,Bob将胜利,Alice失败。
  • n = 4时,Alice可以拿走1,将问题变成n = 3时的Bob先手,Alice胜利。
  • n = 5时,Alice只能拿走1,问题变成n = 4时的Bob先手,Alice失败。

哦豁,看起来是一胜一负呢。n为偶数时,先手必胜。

从感性上理解,由于最小可以拿走1,且最终拿到1的人会失败,那每个人就要避免拿到1。

如果持有奇数,由于奇数乘偶数一定是偶数,而只有奇数乘奇数才是奇数,所以此时无论怎么拿,都只能给对方留下偶数。持有1时除外,已经输了。

如果持有偶数,按照上面的分析,就可以选择给对方奇数还是偶数。

而1是奇数。

在持有奇数只能给对方留下偶数的情况下,奇数当然是先手必败。

class Solution {
public:
    bool divisorGame(int n) {
        return n % 2 == 0;
    }
};

此外,还可以通过动态规划的方式解决。

我们可以清楚的知道先手持有1时必败,先手持有2时必胜,那么当n >= 3时,Alice拿走任意数后,Bob必将处于n = m(m < n)的先手问题上,只要找到一个m是必败的,那么Alice就是必胜的。

定义:dp[i]表示当前数字下先手必胜还是必败。

状态转移方程:dp[i] = true,当存在符合题意操作的j使得 dp[i-j] = false;否则dp[i] = false;

class Solution {
public:
    bool divisorGame(int n) {
        if(n == 1) return false;
        vector<int> dp(n+1,false);
        dp[2] = true;
        for(int i = 3;i <= n;i++){
            for(int j = 1;j < i;j++){
                if(i % j == 0 && !dp[i-j]){
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[n];
    }
};
  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值