[LeetCode] 1025. Divisor Game
Description
Alice and Bob take turns playing a game, with Alice starting first.
Initially, there is a number N
on the chalkboard. On each player's turn, that player makes a move consisting of:
- Choosing any
x
with0 < x < N
andN % x == 0
. - Replacing the number
N
on the chalkboard withN - x
.
Also, if a player cannot make a move, they lose the game.
Return True
if and only if Alice wins the game, assuming both players play optimally.
Example 1:
Input: 2
Output: true
Explanation: Alice chooses 1, and Bob has no more moves.
Example 2:
Input: 3
Output: false
Explanation: Alice chooses 1, Bob chooses 1, and Alice has no more moves.
Note:
1 <= N <= 1000
Analyse
黑板上有个整数N
,每个人都作如下两个操作
- 选择一个整数
x
,x
满足0 < x < N
和N % x == 0
- 将
N
变成N - x
无法选择出满足条件的整数x
时输
Alice先手
两个人作出的选择都是最优的
动态规划
-
定义dp[i] 为当
N
为i,且轮到Alice选择时是否会胜利 -
找出递推关系
dp[i] = true ## 存在x,满足(dp[i - x] == false) && (N % x == 0) && (1 < x < N)
false ## 其他
给出初值
dp[0] = false
dp[1] = true
最终代码
bool divisorGame(int N) {
bool dp[N+1] = {false}; // 用false初始化为长度为N+1的dp数组
for (int i = 2; i <= N; i++) {
for (int x = 1; x < i; x++) {
if (i % x == 0) { // N % x == 0 ?
dp[i] = dp[i] || !dp[i-x]; // dp[i - x] == false ?
}
}
}
return dp[N];
}
找规律
对这道题来说,只有N
一个输入,且N
定义的是dp的长度,dp的值对于所有的N
来说都是一样的,可以先手动算几个,这里计算N=6
N | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
结果 | x | √ | x | √ | x | √ |
N=2时,Alice选择x=1,胜
N=3时,Alice选择x=1,败
N=4时,Alice选择x=1,Bob面对N=3的情况,Alice胜,这里Alice如果选择2的话就输了(但题目说玩家做出的选择都是最优的)
N=5时,Alice选择x=1,Bob面对N=4的情况,Bob胜,Alice败
N=6时,Alice选择x=1,Bob面对N=5的情况,Bob败,Alice胜
看出规律,只要轮到Alice的时候N是偶数,Alice就赢定了
用位运算 (N & 1) == 0 来判断奇偶
bool divisorGame(int N) {
return (N & 1) == 0;
}
简单的证明
-
谁拿1谁就输
-
N为奇数时,Alice必输
奇数的因子也是奇的,无论Alice选什么,剩下的N-x为偶数,x < N,N-x至少为2,Bob再选1,N-x又变成了奇数,重复这个操作,最后Alice会拿到1 -
N为偶数时,Alice必胜
Alice每次选1,Bob就拿到了奇数,Alice胜