题目链接:https://vjudge.net/problem/UVA-12293
题意:
两人玩游戏,有两个盒子,开始时第一个盒子装了n个球, 第二个盒子装了一个球。每次操作都将刷量少的盒子的球倒掉,然后再从数量多的盒子中拿出若干个球放到空盒子里,最终状态为(1,1),达到这个状态的玩家获胜。
题解:
1.由于每次都是倒掉数量少的那个盒子,再对数量多的盒子进行分割,所以可以把规则简化为:初始时有n个球,每次只能拿走不多于n/2的球,最终状态为1个球,达到这个状态的玩家获胜。
2.简化游戏规则之后,可知这是一个典型的SG博弈,但是由于n的范围很大,不能直接求SG值,那就打表找规律,如下:
可知,当n为 2^i - 1时,先手输;否则先手赢。
代码一:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const int INF = 2e9; 15 const LL LNF = 9e18; 16 const int MOD = 1e9+7; 17 const int MAXN = 100+10; 18 19 int SG[MAXN], vis[MAXN]; 20 void table() 21 { 22 SG[1] = 0; 23 for(int i = 2; i<=35; i++) 24 { 25 memset(vis, 0, sizeof(vis)); 26 for(int j = (i+1)/2; j<i; j++) vis[SG[j]] = 1; 27 for(int j = 0;;j++) if(!vis[j]) { 28 SG[i] = j; 29 break; 30 } 31 } 32 for(int i = 1; i<=32; i++) printf("%-2d ",i); putchar(' '); 33 for(int i = 1; i<=32; i++) printf("%-2d ",SG[i]); putchar(' '); 34 /* 35 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 36 0 1 0 2 1 3 0 4 2 5 1 6 3 7 0 8 4 9 2 10 5 11 1 12 6 13 3 14 7 15 0 16 37 */ 38 } 39 40 bool judge(int x) 41 { 42 x++; 43 int bit = 0; 44 while(x) 45 { 46 bit += x&1; 47 x >>= 1; 48 } 49 return bit==1; 50 } 51 52 53 int main() 54 { 55 // table(); 56 int n; 57 while(scanf("%d", &n) &&n) 58 { 59 if(judge(n)) printf("Bob "); 60 else printf("Alice "); 61 } 62 }
代码二:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const int INF = 2e9; 15 const LL LNF = 9e18; 16 const int MOD = 1e9+7; 17 const int MAXN = 100+10; 18 19 int SG[MAXN], vis[MAXN]; 20 void table() 21 { 22 SG[1] = 0; 23 for(int i = 2; i<=32; i++) 24 { 25 memset(vis, 0, sizeof(vis)); 26 for(int j = (i+1)/2; j<i; j++) vis[SG[j]] = 1; 27 for(int j = 0;;j++) if(!vis[j]) { 28 SG[i] = j; 29 break; 30 } 31 } 32 for(int i = 1; i<=32; i++) printf("%-2d ",i); putchar(' '); 33 for(int i = 1; i<=32; i++) printf("%-2d ",SG[i]); putchar(' '); 34 /* 35 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 36 0 1 0 2 1 3 0 4 2 5 1 6 3 7 0 8 4 9 2 10 5 11 1 12 6 13 3 14 7 15 0 16 37 */ 38 } 39 40 int main() 41 { 42 // table(); 43 int n; 44 while(scanf("%d", &n) &&n) 45 { 46 if(n&(n+1)) printf("Alice "); 47 else printf("Bob "); 48 } 49 }