题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3576
很显然,这是一个multi-nim游戏。
注意:1.一个点的SG值就是一个不等于它的后继点的SG的且大于等于零的最小整数。(mex)
2.主游戏的SG值等于所有子游戏的异或和
所以区分好主游戏和后继点的区别。
一开始多个石子堆组合起来形成了一个主游戏。
一个石子堆可以分为多个石子堆,每一种分发构成了一个主游戏,这些主游戏的异或和构成的当前这个点(状态)的SG函数。
显然有一个${m^{2}}$做法,即记忆化搜索SG函数。
考虑${x/i}$只有$sqrt{n}$种取值,再考虑一下它们的奇偶性,然后分块来做。
70Code:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<cstdlib> 6 #include<cmath> 7 #include<cstring> 8 using namespace std; 9 #define maxn 100100 10 #define llg long long 11 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); 12 llg n,m,bj[maxn],sg[maxn],T,F,a[maxn]; 13 14 llg dp(llg x) 15 { 16 if (bj[x]) return sg[x]; 17 bj[x]=1; 18 sg[x]=0; 19 bool e[maxn]; 20 memset(e,0,sizeof(e)); 21 for (llg m=2;m<=x;m++) 22 { 23 llg v1=m-x%m,v2=x%m; 24 llg nsg=0; 25 if (v1&1) nsg^=dp(x/m); 26 if (v2&1) nsg^=dp(x/m+1); 27 e[nsg]=1; 28 } 29 for (llg i=0;1;i++) if (!e[i]) {sg[x]=i; return sg[x];} 30 } 31 32 int main() 33 { 34 yyj("game"); 35 cin>>T>>F; 36 for (llg i=0;i<F;i++) bj[i]=1; 37 while (T--) 38 { 39 scanf("%lld",&n); 40 llg ans=0; 41 for (llg i=1;i<=n;i++) 42 { 43 scanf("%lld",&a[i]); 44 ans^=dp(a[i]); 45 } 46 if (ans) printf("1");else printf("0"); 47 if (T) printf(" "); 48 } 49 return 0; 50 }
100Code:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<cstdlib> 6 #include<cmath> 7 #include<cstring> 8 using namespace std; 9 #define maxn 100100 10 #define llg int 11 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); 12 llg n,m,bj[maxn],sg[maxn],T,F,a[maxn]; 13 14 llg dp(llg x) 15 { 16 if (bj[x]) return sg[x]; 17 bj[x]=1; 18 sg[x]=0; 19 bool e[maxn]; 20 memset(e,0,sizeof(e)); 21 for (llg m=2,j=0;m<=x;m=j+1) 22 { 23 j=x/(x/m); 24 llg v1=m-x%m,v2=x%m,cnt=j-m+1; 25 llg nsg=0; 26 if (v1&1) nsg^=dp(x/m); 27 if (v2&1) nsg^=dp(x/m+1); 28 e[nsg]=1; 29 if (cnt>=2) 30 { 31 nsg=0; 32 if (((m+1)-x%(m+1))&1) nsg^=dp(x/(m+1)); 33 if ((x%(m+1))&1) nsg^=dp(x/(m+1)+1); 34 e[nsg]=1; 35 } 36 } 37 for (llg i=0;1;i++) if (!e[i]) {sg[x]=i; return sg[x];} 38 } 39 40 int main() 41 { 42 yyj("game"); 43 cin>>T>>F; 44 for (llg i=0;i<F;i++) bj[i]=1; 45 while (T--) 46 { 47 scanf("%d",&n); 48 llg ans=0; 49 for (llg i=1;i<=n;i++) 50 { 51 scanf("%d",&a[i]); 52 ans^=dp(a[i]); 53 } 54 if (ans) printf("1");else printf("0"); 55 if (T) printf(" "); 56 } 57 return 0; 58 }