HDU 4764 Stone (巴什博弈)

題意

Tang和Jiang玩石子游戲,給定n個石子,每次取[1,k]個石子,最早取完的人失敗,Tang先取,問誰是贏家。

思路

比賽的時候想了不久,還WA了一次= =……後來看題解才發現是經典的 巴什博弈,博弈什麼的什麼都不會= =…… 【 巴什博弈】只有一堆n個物品,兩我的輪流從這堆物品中取物,規定每次至少取一個,最多取m個。最後取光者得勝。 分析:顯然,若是n=m+1,那麼因爲一次最多隻能取m個,因此,不管先取者拿走多少個,後取者都可以一次拿走剩餘的物品,後者取勝。所以咱們發現瞭如何取勝的法則:若是n=(m+1)r+s,(r爲任意天然數,s≤m),那麼先取者要拿走s個物品,若是後取者拿走k(≤m)個,那麼先取者再拿走m+1-k個,結果剩下(m+1)(r-1)個,之後保持這樣的取法,那麼先取者確定獲勝。總之,要保持給對手留下(m+1)的倍數,就能最後獲勝。 【 結論n % (m+1) == 0,後手必勝;不然先手必勝。 【 變形】若是規定最後取光者輸,結果如何? (n-1)%(m+1) == 0,後手必勝。 分析:先手會從新決定策略,因此不是簡單的相反行的。咱們這樣想:若是保證最後給先手只留一個,那麼後手就能必勝了。問題就化爲取n-1個的子問題,而最後是後手取走的,因此對應的是巴什博弈後手必勝即(n-1) % (m+1) == 0的狀況。

代碼

  [cpp] #include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <string> #include <cstring> #include <vector> #include <set> #include <stack> #include <queue> #define MID(x,y) ((x+y)/2) #define MEM(a,b) memset(a,b,sizeof(a)) #define REP(i, begin, end) for (int i = begin; i <= end; i ++) using namespace std; int main(){ //freopen("test.in", "r", stdin); //freopen("test.out", "w", stdout); int n, k; while(scanf("%d %d", &n, &k) != EOF){ if (n + k == 0) break; if ((n-1) % (k+1) == 0){ puts("Jiang"); } else{ puts("Tang"); } } return 0; } [/cpp]
相關文章
相關標籤/搜索