UVA1482 Playing With Stones —— SG博弈

 

题目链接:https://vjudge.net/problem/UVA-1482

 

 

 

题意:

有n堆石子, 每堆石子有ai(ai<=1e18)。两个人轮流取石子,要求每次只能从一堆石子中抽取不多于一半的石子,最后不能取的为输家。

 

题解:

典型的SG博弈,由于ai的范围很大,所以不能直接求SG值,那么就打表SG值找规律,如下:

 

发现,当x为偶数时, SG[x] = x/2; 当x为奇数时, SG[x] = SG[x/2],即如下:

 

 

代码如下:

 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[0] = SG[1] = 0;
23     for(int i = 2; i<=30; i++)
24     {
25         memset(vis, 0, sizeof(vis));
26         for(int j = 1; j<=i/2; j++) vis[SG[i-j]] = 1;
27         for(int j = 0;;j++) if(!vis[j]) {
28             SG[i] = j;
29             break;
30         }
31     }
32 
33     for(int i = 0; i<=30; i++) printf("%-2d ",i); putchar('\n');
34     for(int i = 0; i<=30; i++) printf("%-2d ",SG[i]); putchar('\n');
35     putchar('\n');
36     for(int i = 0; i<=30; i+=2) printf("%-2d ",i); putchar('\n');
37     for(int i = 0; i<=30; i+=2) printf("%-2d ",SG[i]); putchar('\n');
38     putchar('\n');
39     for(int i = 1; i<=30; i+=2) printf("%-2d ",i); putchar('\n');
40     for(int i = 1; i<=30; i+=2) printf("%-2d ",SG[i]); putchar('\n');
41 /*
42     0  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
43     0  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
44 
45     0  2  4  6  8  10 12 14 16 18 20 22 24 26 28 30
46     0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15
47 
48     1  3  5  7  9  11 13 15 17 19 21 23 25 27 29
49     0  0  1  0  2  1  3  0  4  2  5  1  6  3  7
50 */
51 }
52 
53 LL getSG(LL x){
54     return x%2==0?x/2:getSG(x/2);
55 }
56 
57 int main()
58 {
59 //    table();
60     int T, n;
61     scanf("%d", &T);
62     while(T--)
63     {
64         LL a, v = 0;
65         scanf("%d", &n);
66         for(int i = 1; i<=n; i++)
67         {
68             scanf("%lld", &a);
69             v ^= getSG(a);
70         }
71 
72         if(v) printf("YES\n");
73         else printf("NO\n");
74     }
75 }
View Code

 

posted on 2018-01-24 14:50  h_z_cong  阅读(230)  评论(0编辑  收藏  举报

导航