【BZOJ1874】取石子游戏(SG函数)

题意:小H和小Z正在玩一个取石子游戏。 取石子游戏的规则是这样的,每个人每次可以从一堆石子中取出若干个石子,

每次取石子的个数有限制,谁不能取石子时就会输掉游戏。 小H先进行操作,

他想问你他是否有必胜策略,如果有,第一步如何取石子

n<=10,a[i]<=1000,m<=10,b[i]<=10

思路:求一下SG函数再枚举一下方案……

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cmath>
 6 typedef long long ll;
 7 using namespace std;
 8 #define N   21000
 9 #define oo  10000000
10 #define MOD 1000000007
11 
12 int a[N],b[N],c[N],flag[N],g[N],n;
13 
14 int isok(int x,int y)
15 {
16     a[x]-=y;
17     int ans=0;    
18     for(int i=1;i<=n;i++) ans^=g[a[i]];
19     a[x]+=y;
20     if(ans) return 0;
21     return 1;
22 }
23 
24 int main()
25 { 
26     scanf("%d",&n);
27     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
28     int m;
29     scanf("%d",&m);
30     memset(c,0,sizeof(c));
31     for(int i=1;i<=m;i++) 
32     {
33         scanf("%d",&b[i]);
34         c[b[i]]=1;
35     }
36     g[0]=0;
37     for(int i=1;i<=1000;i++)
38     {
39         memset(flag,0,sizeof(flag));
40         for(int j=1;j<=m;j++)
41          if(i-b[j]>=0) flag[g[i-b[j]]]=1;
42         int j=0;
43         while(flag[j]) j++;
44         g[i]=j;
45     }
46     int ans=0;
47     for(int i=1;i<=n;i++) ans^=g[a[i]];
48     if(ans) 
49     {
50         int s1=0; int s2=0;
51         for(int i=1;i<=n;i++)
52          for(int j=1;j<=a[i];j++)
53           if(s1+s2==0&&c[j]&&isok(i,j)){s1=i; s2=j;}
54         printf("YES\n");
55         printf("%d %d\n",s1,s2);
56     }
57      else printf("NO\n");
58     return 0;
59 }
60     

猜你喜欢

转载自www.cnblogs.com/myx12345/p/9954213.html
今日推荐