取石子游戏 bzoj-1874 BeiJing2009 WinterCamp
题目大意:题目链接。
注释:略。
想法:
我们通过$SG$函数的定义来更新$SG$的转移。
如果是寻求第一步的话我们只需要求一下到底是哪个使得$SG$值是0即可。
Code:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define N 15 #define V 1010 using namespace std; int sg[V],a[N],b[N]; int n,m; inline char nc() {static char *p1,*p2,buf[100000]; return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;} int rd() {int x=0; char c=nc(); while(!isdigit(c)) c=nc(); while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=nc(); return x;} int SG(int x) { if(x<0) return 1001; if(sg[x]!=-1) return sg[x]; bool vis[V]; memset(vis,false,sizeof vis); for(int i=1;i<=m;i++) vis[SG(x-b[i])]=true; for(int i=0;i<=1000;i++) { if(!vis[i]) return sg[x]=i; } } int main() { memset(sg,-1,sizeof sg); n=rd(); for(int i=1;i<=n;i++) a[i]=rd(); m=rd(); for(int i=1;i<=m;i++) b[i]=rd(); int ans=0; for(int i=1;i<=n;i++) ans^=SG(a[i]); if(ans) { puts("YES"); for(int i=1;i<=n;i++) { int now=ans^SG(a[i]); for(int j=1;j<=m;j++) { if(a[i]>=b[j]) { if(!(now^SG(a[i]-b[j]))) { printf("%d %d ",i,b[j]); return 0; } } } } } puts("NO"); // for(int i=0;i<=10;i++) printf("%d ",SG(i)); return 0; }
小结:无。