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]
相关文章
相关标签/搜索