BZOJ 1874: [BeiJing2009 WinterCamp]取石子游戏 [Nim游戏 SG函数]
小H和小Z正在玩一个取石子游戏。 取石子游戏的规则是这样的,每个人每次可以从一堆石子中取出若干个石子,每次取石子的个数有限制,谁不能取石子时就会输掉游戏。 小H先进行操作,他想问你他是否有必胜策略,如果有,第一步如何取石子。
N≤10 Ai≤1000
裸SG函数啊
然而我连SG函数都不会求了,WA了一会儿之后照别人代码改发现vis公用了...
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; typedef long long ll; const int N=15,M=1005; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int n,a[N],m,b[N]; int sg[M],vis[M]; int dfs(int u){//printf("dfs %d\n",u); if(sg[u]!=-1) return sg[u];//printf("y\n"); bool vis[N];memset(vis,0,sizeof(vis)); for(int i=1;i<=m && b[i]<=u;i++) vis[dfs(u-b[i])]=1; for(int i=0;;i++) if(!vis[i]) {sg[u]=i;break;} return sg[u]; } int main(){ //freopen("in","r",stdin); memset(sg,-1,sizeof(sg));sg[0]=0; n=read(); for(int i=1;i<=n;i++) a[i]=read(); m=read(); for(int i=1;i<=m;i++) b[i]=read(); sort(b+1,b+1+m); int sum=0; for(int i=1;i<=n;i++) sum^=dfs(a[i]); if(sum!=0){ puts("YES"); int flag=0; for(int i=1;i<=n && !flag;i++) for(int j=1;j<=m && b[j]<=a[i];j++) if( ( sum^dfs(a[i])^dfs(a[i]-b[j]) )==0 ) {printf("%d %d\n",i,b[j]);flag=1;break;} }else puts("NO"); }
Copyright:http://www.cnblogs.com/candy99/