1025 除数博弈
爱丽丝和鲍勃一起玩游戏,他们轮流行动。爱丽丝先手开局。
最初,黑板上有一个数字 N
。在每个玩家的回合,玩家需要执行以下操作:
选出任一 x
,满足 0 < x < N
且 N % x == 0
。
用 N - x
替换黑板上的数字 N
。
如果玩家无法执行这些操作,就会输掉游戏。
只有在爱丽丝在游戏中取得胜利时才返回True
,否则返回 false
。假设两个玩家都以最佳状态参与游戏。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/divisor-game
示例 1:
输入:2
输出:true
解释:爱丽丝选择 1,鲍勃无法进行操作。
示例 2:
输入:3
输出:false
解释:爱丽丝选择 1,鲍勃也选择 1,然后爱丽丝无法进行操作。
力扣中已经有许许多多的题解了,相信很多也比我写的详细,在这里只是想自己把自己的思路记录下来,汇总到一起,以便日后复习巩固。
法一:
奇偶性判断
由于爱丽丝先手开局,当
N
N
N为偶数时,爱丽丝选择
x
=
1
x = 1
x=1,则鲍勃遇到的 为奇数,由于
N
%
x
=
=
0
N \% x == 0
N%x==0中当
N
N
N为奇数时,
x
x
x必定为奇数,所以此时
N
−
x
N-x
N−x又为偶数。爱丽丝继续选择
1
1
1,鲍勃得到的又是奇数。直到最后爱丽丝得到
2
2
2,爱丽丝选择
1
1
1,鲍勃无法操作。爱丽丝取胜。
当
N
N
N为奇数时,爱丽丝则变为了上面情况的鲍勃,最后一定失败。
class Solution {
public:
bool divisorGame(int N) {
if (N%2==0) return true;
return false;
}
};
法二:动态规划
用
d
p
[
i
]
dp[i]
dp[i]来表示当初始值是
i
i
i时爱丽丝的输赢情况。
d
p
[
0
]
=
0
;
d
p
[
1
]
=
0
;
d
p
[
2
]
=
1
;
dp[0] = 0; dp[1]=0;dp[2]=1;
dp[0]=0;dp[1]=0;dp[2]=1;
d
p
[
i
]
dp[i]
dp[i]的判断和前面有关系,当
i
i
i前面的
j
∈
[
1
,
i
−
1
]
j\in[1,i-1]
j∈[1,i−1]中有i%j==0
并且dp[i-j]==0
(因为下一步鲍勃得到的值是
i
−
j
i-j
i−j,
d
p
[
i
−
j
]
=
0
dp[i-j]=0
dp[i−j]=0说明鲍勃是输的) 则
d
p
[
i
]
=
1
dp[i]=1
dp[i]=1,否则
d
p
[
i
]
=
0
dp[i]=0
dp[i]=0。
class Solution {
public:
bool divisorGame(int N) {
if (N<=1) return false;
vector<int> v(N+1);
v[0]=0,v[1]=0,v[2]=1;
for(int i = 3;i <= N; i++)
{
v[i]=0;
for(int j=1;j<i;j++)
{
if (i%j==0&&v[i-j]==0)
{
v[i]=1;break;//有一个使爱丽丝赢得情况即可
}
}
}
return v[N]==1;
}
};