题意,nim游戏,n堆石子,可在一堆中取任意个,也可把一堆分为三堆,最后取完的胜
思路:打表找规律。。x=8k+7时,sg[x]=x+1,x=8k+8时,sg[x]=x-1,其余情况,sg[x]=x。
比赛时以为x一定能转移到0~x-1的状态的,还在二进制表示中找到了一个特别神奇的规律。。血崩
其实sg[8]可以转移到sg[0]~sg[7],但sg[7]的值为8,所以sg[8]的值就为7。。
打表代码:
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<sstream>
#include<iostream>
#include<cmath>
#include<queue>
#include<map>
#include<set>
using namespace std;
int main(){
// freopen("out.txt","w",stdout);
char str[100];
int sg[10000],MAX;
int vis[10000];
memset(vis,0,sizeof(vis));
memset(sg,0,sizeof(sg));
set<int> s;
sg[0]=0;
for(int i=1;i<100;i++){
s.clear();
for(int j=0;j<i;j++){
s.insert(sg[j]);
}
for(int a=i-2;a>0;a--){
for(int b=a-1;b>0;b--){
for(int c=a-1;c>0;c--){
if(a+b+c==i){
s.insert(sg[a]^sg[b]^sg[c]);
}
}
}
}
int res=0;
while(s.count(res)) res++;
sg[i]=res;
printf("sg[%d]=%d\n",i,sg[i]);
}
}
ac代码
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<sstream>
#include<iostream>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
int main(){
// freopen("in.txt","r",stdin);
int t;
cin>>t;
while(t--){
int n,a;
scanf("%d",&n);
int ans=0;
for(int i=0;i<n;i++){
scanf("%d",&a);
if(a%8==0){
ans^=a-1;
}else if(a%8==7)
ans^=a+1;
else
ans^=a;
}
if(ans!=0){
printf("First player wins.\n");
}else{
printf("Second player wins.\n");
}
}
return 0;
}