【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
null