(leetcode292)Nim游戏(位运算的巧妙用法)

原题如下:
在这里插入图片描述
思路:
这是一道简单的题,难点在于考虑题中“都是聪明人,聪明人如何移动”这个地方,因为我们先手,这时候分两种情况:n能否被4整除。

1、n不能被4整除,例如1,2,3,5,6,7这种,我们可以控制我们每次取之后的结果都是4的倍数,这样无论对面拿几个,他一定拿不到最后一个,这相当于我们保证他赢不了
2、n可以被4整除,这时候我们一定输,因为这时候我们拿了以后相当于让对面可以控制他每次取之后的结果都是4的倍数,我们就赢不了。

这是直观的理解,证明可以用数学归纳法,这里笔者略去。

因此这个问题可以判断是否是4的倍数,是则返回False,否则返回True。

代码:

class Solution:
    def canWinNim(self, n: int) -> bool:
        if n%4==0:
            return False
        return True

划重点!

这里有一个用位运算代替模运算的技巧,

在a%b这种情形下,如果b是2的倍数,a%b=a&(b-1)

下面是其正确性的解释:

我们以数字4为例,
(1)因为是模运算,二进制中>=4的位置部分可以直接抹去,
因为他们分别代表数字481632...,都能整除4,这时候我们通过&00...00xx实现。
(2)对于后面2位,我们保留下来,就是我们求的余数,通过&11实现。
因此整体相当于&00..0011,也就是&n-1。


推广到所有2的倍数,对其进行模运算时,其二进制中1以及之前的位置都直接抹去,
1之后的位置保留,结果即为余数,即为a%b=a&(b-1)

特别有用的一点是,当b为2时,公式为

a%2=a&1

因为位运算比取模快得多,在判断数字奇偶的情况时可以用a&1来判断

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值