題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1525
一,題意:
給定兩個整數N,M,Stan與Ollie輪流從較大的數中減去較小數的整數倍,但是該倍數
不能超過較大的數,即運算後的結果不能爲負數。從stan開始,若誰能將一個數變爲0
則其獲勝。
二,解析:
我們分析一下對於當前狀態爲(a、b)怎麼判斷該狀態是否爲奇異態,我們令a>b
(如果不大於可以交換),有下列幾種情況:
1,若a%b==0 則只是面對該狀態的人必勝。
2,若a%b!=0 這 有兩種狀態 :a - b < b , a - b > b
1)a - b < b ;(即只能在a中減去一倍b) 這樣面對這一狀態的人沒有選擇的餘地。
只能將狀態(a,b)轉移到狀態 (b,a - b),則(a,b)狀態的勝敗取決於(b,a - b)
狀態。這是我們需要遞推求解(a,b)狀態的勝敗。
2)a - b > b 則:a - b * x < b (x >= 2); 我們先考慮 (a - (x - 1) * b,b) ;若該狀態爲必勝點,
而 (a - (x - 1) * b,b) 是 1) 的情況因爲: a - (x - 1) * b - b < b , 所以該狀態 下一個狀態只能
是(a - x * b ,b)由於 (a - (x - 1) * b,b) 是必敗點則 (a - x * b,b) 爲必敗點,這時若我們直接
從(a,b)到達 (a - x * b,b) 則 必勝。 所以無論誰面對 2)狀態必勝。
三,代碼:
#include <iostream>
#include <stdio.h>
using namespace std;
int N,M;
int main()
{
while(scanf("%d%d",&N,&M)!=EOF)
{
if(!N && !M)
break;
if(N<M)
swap(N,M);
int x=0;
while(1)
{
if(N%M==0 || N-M > M)
break;
int key=M;
M=N-M;
N=key;
x=x^1;
}
if(x)
printf("Ollie wins\n");
else
printf("Stan wins\n");
}
return 0;
}