25 7 11 7 4 7 4 3 1 3 1 0
an Stan wins.
34 12 15 24 0 0Sample Output
Stan wins Ollie wins
題意:
讓我們看一下這個以輾轉相除法爲基礎的遊戲。
給定兩個整數a和b。Stan和Ollie輪流從較大的數字中減去較小數字的倍數。這裏的倍數指的是1倍、2倍等這樣的正整數倍,並且相減後的結果不能小於零。Stan先手,在自己的回合將其中一個數變爲零的一方獲勝。當雙方都採取最優策略時,誰會獲勝?
解題思路:
讓我們來找找看該問題中必勝態和必敗態的規律。首先,如果a>b則交換,假設a<b。另外,如果b已經是a的倍數了則必勝,所以假設b並非a的倍數。此時,a和b的關係,按自由度的觀點,可以分成以下兩類。
(1)b-a<a的情況
(2)b-a>a的情況
對於第一種情況,如果從b中減去a的2倍以上的數則變爲負數,所以只能從b中減去a,沒有選擇的餘地。相對的,對於第二種情況,有從b中減去a,減去2a,或更高的倍數等多種選擇。
對於第一種情況,要判斷必勝還是必敗是很簡單的。因爲沒有選擇的餘地,如果b減去a之後所得到的狀態是必敗態的話,它就是必勝態,如果得到的是必勝態的話,它就是必敗態。
例如,從(4,7)這個狀態出發就完全沒有選擇的機會,按照
(4,7)-->(4,3)-->(1,3)
的順序,輪到(1,3)的一方將獲勝, 所以有
(4,7)-->(4,3)-->(1,3)
必勝-->必敗-->必勝
可見(4,7)是必勝態。
接下來,我們來看一下第二種情況是必勝態還是必敗態。假設x是使得b-ax<a的整數,考慮一下從b中減去a(x-1)的情況。例如對於(4,19)則減去12。
此時,接下來的狀態就成了前邊講過的沒有選擇餘地的第一種情況。如果該狀態是必敗態的話,當前狀態就是必勝態。
那麼,如果減去a(x-1)後的狀態是必勝態的話,該如何是好呢?此時,從b中減去ax後的狀態是減去a(x-1)後的狀態唯一可以轉移到的狀態,根據假設,減去a(x-1)後的狀態是必勝態,所以該狀態是必敗態。因此,當前狀態是必勝態。
例如對於(4,17),由於從17中減去12得到的(4,5)就是必敗態,所以只要減去12就能獲勝。另一方面,對於(4,19),減去12得到的(4,7)是必勝態,因此(4,3)就是必敗態,只要減去16就能獲勝。
由此可知,第二種情況總是必勝的。所以,從初始狀態開始,最先到達有自由度的第二種狀態的一方必勝。
AC代碼:
#include<stdio.h>
#include<algorithm>
using namespace std;
int main()
{
int a,b;
while(~scanf("%d%d",&a,&b)&&a&&b)
{
bool f=true;
for(;;)
{
if(a>b) swap(a,b);
if(b%a==0) break;//b是a的倍數時必勝
if(b-a>a) break;//如果是第二種情況必勝
b-=a;
f=!f;
}
if(f) printf("Stan wins\n");
else printf("Ollie wins\n");
}
return 0;
}