洛谷 P2148 [SDOI2009]E&D(SG函数入门)
题意:略
思路:很显然我们拆分成n/2个游戏,然后对每个游戏求sg函数,最后计算一下总和即可,规律我就不写了,很多聚聚的博客上面都有,我贴一份sg的代码
代码:(其实这是ac代码)
#include<bits/stdc++.h> using namespace std; typedef long long LL; inline LL read() { LL x=0,f=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int sg(int x,int y) { int a=x,b=y,ans=0; while(true){ if(a&1&&b&1)return ans; if(a&1)a++; if(b&1)b++; a>>=1;b>>=1;ans++; } } int main() { int T=read(); while(T--) { int n=read(); n/=2; int x,y,ans=0; for(int i=1;i<=n;i++) { scanf("%d%d",&x,&y); ans^=sg(x,y); } if(ans) puts("YES"); else puts("NO"); } return 0; } /* 10 10 */
(这才是SG的)
#include <bits/stdc++.h> using namespace std; int n,m; int sg[1005][1005]; int dfs(int x,int y){ if(x==1 && y==1){ sg[1][1]=0;return 0; } if(sg[x][y]!=-1) return sg[x][y]; int vis[1007]; if(x!=1) for(int i=1;i<=x/2;i++) vis[dfs(i,x-i)]=true; if(y!=1) for(int i=1;i<=y/2;i++) vis[dfs(i,y-i)]=true; for(int i=0;i<=1000;i++){ if(vis[i]==false){ sg[x][y]=i; return i; } } } int main(){ memset(sg,-1,sizeof(sg)); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(sg[i][j]==-1)dfs(i,j); } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(sg[i][j])printf("%d ",sg[i][j]); else printf(" "); } printf("\n"); } } /* 20 20 30 30 */