題目描述
給定一個 n 和 k,一個小兵初始位置在長度爲 n 的線段上的第 n 個點,每次可以向左走 1 / 2 / k 格,Alice先移動這個小兵,Bob後移動這個小兵,最後不能移動的人爲輸家,問誰能獲勝。
思路
在沒有 k 的情況下考慮
當 n % 3 == 0 時,Bob 必能能走出一種走法使得每次移動到的位置都是3的倍數,Bob必勝狀態
當 n % 3 == 1 或者 n % 3 == 2, Alice 必有一種走法使得每次讓小兵移動的位置到 3 的倍數上面,把必敗態轉移給 Bob
加入 k 的狀態時,需要考慮兩種情況
1. k % 3 != 0
可以直接看成每次移動了 1 格或者 2 格,例如 k = 偶數 的時候,其爲 2 的倍數,可以看成是走了多個 2 格的狀態,當 k = 奇數 且 k % 3 != 0 時,可以看成走了多個 1 格狀態。
所以給狀態下 Bob 的必勝態:
if(k % 3 != 0)
if(n % 3 == 0)
puts("Bob");
2. k % 3 == 0
可以知道當在 k 點時,可以直接移動到 0,爲必勝態,接下來就需要考慮 k + 1 位置的一個狀態。第 k + 1 位置的狀態走 1 格到 k 狀態會讓對手勝,走 2 格走到 k - 1 狀態,因爲 (k - 1) % 3 != 0,根據最開始分析的三種情況,也是讓對手勝,走 k 格到 1 狀態,也是讓對手勝,所以 k + 1 位置是一個必敗點。Bob想要贏就必須要讓 Alice 走到這個必敗點。根據最先三種情況考慮,要讓 Alice 走到 k + 1 點,因爲中間有大量的重複路段,其實就是要 Alice 走到 m = n % (1 + k) 這個點,且這個 m 點不能等於 0,結合一下開始的 n % 3 == 0 的狀態,Alice必走到這個點的狀態就是 m % 3 == 0
最後注意一下這個 m != k,Alice直接獲勝
if(k % 3 != 0) {
int m = n % (k + 1);
if(m % 3 == 0 && m != k)
puts("Bob");
}
代碼
#include<bits/stdc++.h>
using namespace std;
void solve() {
int n, k;
cin >> n >> k;
if(k % 3 != 0) {
if(n % 3 == 0) {
puts("Bob");
return;
}
}
else {
int m = n % (k + 1);
if(m % 3 == 0 && m != k) {
puts("Bob");
return;
}
}
puts("Alice");
}
int main() {
int t; scanf("%d", &t); while(t--)
solve();
return 0;
}