LeetCode 1025. Divisor Game C++

13 篇文章 0 订阅

Problem

题目链接

Solution

题意为,Alice和bob玩一个游戏,给定一个数字N,每个人从(0,N)这个区间选出一个能被N整除的因子x(N%x==0),然后N替换为N-x,换对手重复这个过程,若谁无法重复这个过程了谁就输了。alice先手。

这道题我最初的做法就是手动列了前9次游戏的可能性,发现如果初始的N是偶数,就是alice赢,初始的N是奇数,就是bob赢。

class Solution {
public:
    bool divisorGame(int N) {
        return N&1?false:true;
    }
};

一开始就找了个规律,也没有严格证明。

其实这么想

假设如果到了某一步,轮到Alice下,还没变换的N是奇数

那么有一个结论:这个N经过这步变换后不可能还是奇数

证明:若N是奇数,x是N的一个因子且N-x要为奇数,那么x一定是偶数,那么N至少要有2这个因子,与N是奇数矛盾

那么这一步下完之后alice把N变成了一个偶数,Bob需要处理这个局面

Bob可以减去1,继续保持N为一个奇数的状况,重复上述,alice只能继续把N变成偶数 …

那么当N一直缩小至1(这一步必定是bob来操作,因为bob用最优决策下,Alice处理完后N一定是偶数)

N=1,Alice无法操作,bob就赢了

上述假设把Alice换成bob,bob换成alice同样成立

因此,初始N为偶,alice赢,否则bob赢

证毕

线性Dp做法:

对于每个初始的N,找出所有因子x,若dp[N-x]==false,那证明Alice可以取x做第一步操作,且给bob留下了一个必输的局面,因此alice必赢,若对于所有x,Alice都无法赢,则bob赢。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值