“東信杯”廣西大學第一屆程式設計競賽(同步賽)D、數論只會GCD 【博弈 分類討論】
阿新 • • 發佈:2018-11-27
傳送門:https://ac.nowcoder.com/acm/contest/283/D
題目描述
小西買了一堆肥宅快樂水和肥宅快樂茶,準備和室友比誰更肥宅。 快樂水有A瓶,快樂茶B瓶。 小西和室友的規則是這樣的: 1. 小西先手,輪流到每個人的回合,每個回合只能喝剩餘數量較多的飲料 2. 滿足規則1的同時,每次只能喝另一種飲料剩餘數量的正整數倍 3. 滿足1、2的同時,不能超額喝飲料,也就是說剩下2瓶的時候不能喝大於2瓶的數量。 4. 每個人在自己的回合如果能喝完剩下的其中一種飲料,那麼就獲得勝利。 例如A=10,B=2。 小西只能喝快樂水,且只能喝2/4/6/8/10瓶快樂水。小西可以喝10瓶快樂水直接獲得勝利。 小西和室友都是肥宅,所以他們都會才採取為了勝利最優的行動。 現在請你判斷小西是否能贏得勝利。輸入描述:
輸出描述:
對於每組資料,若小西可以獲得勝利則輸出一行“wula”,否則輸出一行“mmp”,不需要輸出引號示例1
輸入
複製2 20 18 10 4
輸出
複製mmp wula
題意概括:如題
解題思路:
模擬一遍,博弈的規律很清晰。
處理一下保證 A > B,並且兩者除掉GCD縮小範圍,最後得出結果是等價的(兩者除以相同倍數,和每次做減法是減少相同的數,對最後能否整除沒有影響)。
遞迴判斷 cheak(A, B,cnt)是先手贏或是後手贏,cnt用於記錄奇偶性(由當前結果回溯到最初的結果)
①如果當前 A%B == 0 先手贏
②如果當前 A/B >= 2 先手贏 (因為我存在至少兩種選擇,裡面必有一種是失敗的,而另外一種肯定是勝利的)
為什麼呢?
如果A/B == 2 ,我們至少擁有減 2 個 B的權利,如果我減一個B最後導致我失敗了對手勝利了,那我肯定減兩個B,就相當於我通過多減一個B跳過了一步,而我成為了成功的那個對手。
如果減一個B成功了,那就成功啦
如果 A/B > 2, 我們其實還是回到上面的結論,減一個或減兩個,其餘的都是附加在這一個或者兩個上的,保證奇偶性即可。
③以上兩種情況不滿足說明當前狀態無法判斷誰會獲勝,需要做一次減法 A-B,遞迴 cheak( A-B,B,++cnt)或者check(B,A-B,++cnt)判斷接下來那個會獲勝,因為記錄了奇偶性,最後可以回溯到最初狀態。
AC code:
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 #define LL long long 6 using namespace std; 7 LL a, b; 8 9 LL GCD(LL a, LL b) 10 { 11 if(b == 0) return a; 12 return GCD(b, a%b); 13 } 14 15 bool check(LL A, LL B, LL cnt) 16 { 17 LL gg = GCD(A, B); 18 A = A/gg; 19 B = B/gg; 20 LL t = A/B; 21 if(A%B == 0) { 22 if(cnt%2LL) return true; 23 else return false; 24 } 25 else if(t >= 2){ 26 27 if(cnt%2LL) return true; 28 else return false; 29 30 } 31 else{ 32 if(B%(A-B) == 0) { 33 if(cnt%2LL)return false; 34 else return true; 35 } 36 else{ 37 if(B > (A-B)) return check(B, (A-B), ++cnt); 38 else return check((A-B), B, ++cnt); 39 } 40 } 41 return true; 42 } 43 44 int main() 45 { 46 int T_case; 47 LL tt, cnt = 1LL; 48 LL G; 49 scanf("%d", &T_case); 50 while(T_case--){ 51 cnt = 1LL; 52 scanf("%lld %lld", &a, &b); 53 if(a < b) swap(a, b); 54 if(a%b == 0) puts("wula"); 55 else{ 56 G = GCD(a, b); 57 a = a/G; 58 b = b/G; 59 if(check(a, b, 1LL)) puts("wula"); 60 else puts("mmp"); 61 } 62 } 63 return 0; 64 }View Code