HDU 3404&POJ 3533 Nim积(二维&三维)
(Nim积相关资料来自论文曹钦翔《从“k倍动态减法游戏”出发探究一类组合游戏问题》)
关于Nim积计算的两个函数流程:
代码实现如下:
int m[2][2]={0,0,0,1}; int Nim_Multi_Power(int x,int y) { if(x<2) return m[x][y]; int a=0; for(;;a++) if(x>=(1<<(1<<a))&&x<(1<<(1<<(a+1)))) break; int m=1<<(1<<a); int p=x/m,s=y/m,t=y%m; int d1=Nim_Multi_Power(p,s); int d2=Nim_Multi_Power(p,t); return (m*(d1^d2))^Nim_Multi_Power(m/2,d1); } int Nim_Multi(int x,int y) { if(x<y) return Nim_Multi(y,x); if(x<2) return m[x][y]; int a=0; for(;;a++) if(x>=(1<<(1<<a))&&x<(1<<(1<<(a+1)))) break; int m=1<<(1<<a); int p=x/m,q=x%m,s=y/m,t=y%m; int c1=Nim_Multi(p,s); int c2=Nim_Multi(p,t)^Nim_Multi(q,s); int c3=Nim_Multi(q,t); return (m*(c1^c2))^c3^Nim_Multi_Power(m/2,c1); }
以下是两道用Nim积来实现的博弈题:
(1)HDU 3404 Switch lights:http://acm.hdu.edu.cn/showproblem.php?pid=3404
#include<iostream> #include<cstdio> using namespace std; int m[2][2]={0,0,0,1}; int Nim_Multi_Power(int x,int y) { if(x<2) return m[x][y]; int a=0; for(;;a++) if(x>=(1<<(1<<a))&&x<(1<<(1<<(a+1)))) break; int m=1<<(1<<a); int p=x/m,s=y/m,t=y%m; int d1=Nim_Multi_Power(p,s); int d2=Nim_Multi_Power(p,t); return (m*(d1^d2))^Nim_Multi_Power(m/2,d1); } int Nim_Multi(int x,int y) { if(x<y) return Nim_Multi(y,x); if(x<2) return m[x][y]; int a=0; for(;;a++) if(x>=(1<<(1<<a))&&x<(1<<(1<<(a+1)))) break; int m=1<<(1<<a); int p=x/m,q=x%m,s=y/m,t=y%m; int c1=Nim_Multi(p,s); int c2=Nim_Multi(p,t)^Nim_Multi(q,s); int c3=Nim_Multi(q,t); return (m*(c1^c2))^c3^Nim_Multi_Power(m/2,c1); } int main() { int t,n,x,y; scanf("%d",&t); while(t--) { scanf("%d",&n); int res=0; while(n--) { scanf("%d%d",&x,&y); res^=Nim_Multi(x,y); } if(res) printf("Have a try, lxhgww.\n"); else printf("Don't waste your time.\n"); } return 0; }
(2)POJ 3533 Light Switching Game:http://poj.org/problem?id=3533
上一题是二维Nim积,这道题与之不同的是求三维Nim积,但本质相同。
#include<iostream> #include<cstdio> using namespace std; int m[2][2]={0,0,0,1}; int Nim_Multi_Power(int x,int y) { if(x<2) return m[x][y]; int a=0; for(;;a++) if(x>=(1<<(1<<a))&&x<(1<<(1<<(a+1)))) break; int m=1<<(1<<a); int p=x/m,s=y/m,t=y%m; int d1=Nim_Multi_Power(p,s); int d2=Nim_Multi_Power(p,t); return (m*(d1^d2))^Nim_Multi_Power(m/2,d1); } int Nim_Multi(int x,int y) { if(x<y) return Nim_Multi(y,x); if(x<2) return m[x][y]; int a=0; for(;;a++) if(x>=(1<<(1<<a))&&x<(1<<(1<<(a+1)))) break; int m=1<<(1<<a); int p=x/m,q=x%m,s=y/m,t=y%m; int c1=Nim_Multi(p,s); int c2=Nim_Multi(p,t)^Nim_Multi(q,s); int c3=Nim_Multi(q,t); return (m*(c1^c2))^c3^Nim_Multi_Power(m/2,c1); } int Nim_Multi2(int x,int y,int z) { int t=Nim_Multi(x,y); return Nim_Multi(t,z); } int main() { int n,x,y,z; while(~scanf("%d",&n)) { int res=0; while(n--) { scanf("%d%d%d",&x,&y,&z); res^=Nim_Multi2(x,y,z); } if(res) printf("No\n"); else printf("Yes\n"); } return 0; }