遊戲規則:給定兩個自然數 (a, b),雙方輪流操作,每次將較大數減去較小數的任意正整數倍(結果不得為負)。先使任一數變為 0 者獲勝。輸入多組 (n, m),n,m ≤ 10⁹,n=m=0 結束。輸出先手獲勝輸出 "Stan wins",否則 "Ollie wins"。
這是一個經典的歐幾里得博弈。關鍵在於當較大數 ≥ 2×較小時,先手擁有決定權,必勝;否後雙方被迫唯一操作(減去 1 倍),勝負取決於遞歸深度的奇偶性。
設 a ≥ b:
#include <cstdio>
#include <algorithm>
using namespace std;
int main() {
long long n, m;
while (scanf("%lld%lld", &n, &m) == 2 && (n || m)) {
if (n < m) swap(n, m);
bool firstWin = true; // true 表示當前玩家(Stan)贏
while (true) {
if (m == 0 || n % m == 0 || n >= 2 * m) break;
n = n - m;
swap(n, m);
firstWin = !firstWin;
}
puts(firstWin ? "Stan wins" : "Ollie wins");
}
return 0;
}
每次遞歸至少將較大數減半(類似輾轉相除法),時間 O(log max(n,m)),極快。