/*
*State: ECNU 1328 Yes 236K 0MS C++ 0.96K
*题目大意:
* 给定red、green、blue三种长度分别为c、z、n的矩形条纹,要求
* 用这三种矩形条纹来cover大小为p x 1的game board,第一个不能
* 再cover的选手为输。问先手是否能赢。
*解题思路:
* 好像是变种了的博弈,想想,原来可以用sg来模拟,其实就是先拿掉一些,
* 再把一堆变成两堆的那种Nim博弈。
*/
![]()
View Code
1 #include <iostream>
2 using namespace std;
3
4 const int MAX = 1024;
5 int a[3], sg[MAX];
6
7 void get_sg()
8 {
9 memset(sg, -1, sizeof(sg));
10 bool vst[MAX] = {false};
11 for(int i = 0; i < MAX; i++)
12 {
13 memset(vst, false, sizeof(vst));
14 for(int j = 0; j < 3; j++)
15 {
16 if(i >= a[j])
17 {
18 int t = i - a[j], t2 = t / 2;
19 for(int k = 0; k <= t2; k++)
20 {
21 int s = sg[k] ^ sg[t - k];
22 vst[s] = true;
23 }
24 }
25 }
26 for(int j = 0; j < MAX; j++)
27 {
28 if(!vst[j])
29 {
30 sg[i] = j;
31 break;
32 }
33 }
34 }
35 return ;
36 }
37
38 int main(void)
39 {
40 #ifndef ONLINE_JUDGE
41 //freopen("in.txt", "r", stdin);
42 #endif
43 while(scanf("%d %d %d", &a[0], &a[1], &a[2]) == 3)
44 {
45 get_sg();
46 int m;
47 scanf("%d", &m);
48 for(int i = 0; i < m; i++)
49 {
50 int p;
51 scanf("%d", &p);
52 if(sg[p])
53 printf("1\n");
54 else
55 printf("2\n");
56 }
57 }
58 return 0;
59 }