package dp.divisorGame;
/**
* 1025. 除数博弈
* 爱丽丝和鲍勃一起玩游戏,他们轮流行动。爱丽丝先手开局。
* <p>
* 最初,黑板上有一个数字 N 。在每个玩家的回合,玩家需要执行以下操作:
* <p>
* 选出任一 x,满足 0 < x < N 且 N % x == 0 。
* 用 N - x 替换黑板上的数字 N 。
* 如果玩家无法执行这些操作,就会输掉游戏。
* <p>
* 只有在爱丽丝在游戏中取得胜利时才返回 True,否则返回 False。假设两个玩家都以最佳状态参与游戏。
* <p>
* <p>
* <p>
* 示例 1:
* <p>
* 输入:2
* 输出:true
* 解释:爱丽丝选择 1,鲍勃无法进行操作。
* 示例 2:
* <p>
* 输入:3
* 输出:false
* 解释:爱丽丝选择 1,鲍勃也选择 1,然后爱丽丝无法进行操作。
* <p>
* <p>
* 提示:
* <p>
* 1 <= N <= 1000
* 通过次数78,570提交次数110,824
*/
public class divisorGame {
/**
* N = 1时,很明显Alice无法写任何数,失败;
* N = 2时,Alice只能写1,于是根据上面的结论,Bob无法写任何数,失败,Alice获胜;
* N = 3时,3的唯一小于它的约数为1,Alice只能写2,于是根据上面的结论,Alice失败;
* N = 4时,Alice可以写3,于是Bob失败,她获胜;
* 总而言之,当N为奇数时,Alice失败,而当N为偶数时,Alice获胜。
* <p>
* 递推公式 i%j==0 && !dp[i-j]
* 解释 i代表从i到N,j代表从1到N-1,如果存在合适的除数,就判断N-i的那个位置后手人的状态。
*
* @param n
* @return
*/
public static boolean divisorGame(int n) {
if (n == 1) {
return false;
}
boolean[] dp = new boolean[n + 1];
dp[1] = false;
for (int i = 2; i <= n; i++) {
for (int j = 1; j < i; j++) {
if (i % j == 0 && !dp[i - j]) {
dp[i] = true;
}
}
}
return dp[n];
}
public static void main(String[] args) {
System.out.println(divisorGame(3));
}
}