[AtCoder] Lucky 7 Battle
Assume the first N - 1 rounds have been played and we are left with a %7 value R. There are 2 cases depending on who plays the last round.
1. Aoki wants to get a final value of %7 != 0. Takahashi can only win if 10R % 7 == 0 AND (10R + S[N]) % 7 == 0, otherwise Aoki will play the option of %7 != 0.
2. Takahashi wants to get a final value of % 7 == 0. Takahashi can win if 10R % 7 == 0 OR (10R + S[N]) % 7 == 0.
Generalize this idea and do DP in reverse order.
This is also because to compute the new value of % 7 after an append to end operation at round i, we'll need the results from round i + 1.
Instead of tracking both players in the dp state, only track Takahashi to simplify.
dp[i][j]: if the takahashi can win after round i with j as the % 7 value.
initial state: dp[N][0] = true. (when the result is empty, it is equivalent to have a 0 value, 0 % 7 == 0)
state transition:
if Aoki plays the ith round, dp[i][j] = dp[i + 1][j * 10 % 7] && dp[i + 1][(j * 10 + d) % 7];
if Takahashi plays the ith round, dp[i][j] = dp[i + 1][j * 10 % 7] || dp[i + 1][(j * 10 + d) % 7];
final result: dp[0][0] = true means Takahashi wins otherwise Aoki wins.
//dp[i][j]: if the takahashi can win after round i with j as the % 7 value
dp = new boolean[n + 1][7];
dp[n][0] = true;
for(int i = n - 1; i >= 0; i--) {
int d = s[i] - '0';
if(x[i] == 'A') {
for(int j = 0; j < 7; j++) {
dp[i][j] = dp[i + 1][j * 10 % 7] && dp[i + 1][(j * 10 + d) % 7];
}
}
else {
for(int j = 0; j < 7; j++) {
dp[i][j] = dp[i + 1][j * 10 % 7] || dp[i + 1][(j * 10 + d) % 7];
}
}
}
out.println(dp[0][0] ? "Takahashi" : "Aoki");