来源:HDU5726
多校的一道博弈题,SG函数,打表取抑或,关键是如何打表
代码:
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 20;
int sg[(1<<N)+10];//状态压缩
int vis[20];//由于求MEX函数
int mex(int x){//对于一个状态x
int i,k=-1;
memset(vis,false ,sizeof(vis));
for(int i=0;i<N;i++){
if(!((1<<i)&x))//从小开始找,x状态下
k=i;
else if(k!=-1)
vis[sg[x^(1<<k)^(1<<i)]] = true;
}
for(i=0;i<N;i++)//mex函数定义
if(!vis[i]) return i;
}
void getSG(){
sg[0]=0;
for(int i=1;i<(1<<N);i++){
sg[i]=mex(i);
}
}
int main(){
int T;
getSG();
scanf("%d",&T);
while(T--){
int n,cnt,ans,s;
scanf("%d",&n);
ans=0;
for(int i=0;i<n;i++){
scanf("%d",&cnt);
s=0;
for(int j=0;j<cnt;j++){
int d;
scanf("%d",&d);
s+=(1<<(N-d));//状态记录为S
}
ans^=sg[s];//NIM
}
if(ans) puts("YES");
else puts("NO");
}
return 0;
}
本文介绍了一道多校竞赛中的博弈题目,并通过状态压缩和Sprague-Grundy函数进行解决。文章给出了完整的C++代码实现,展示了如何利用SG函数和状态压缩技巧来求解这类问题。
3055

被折叠的 条评论
为什么被折叠?



