1. 程式人生 > >【BZOJ1874】取石子游戲(SG函式)

【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