题意:
1*n的格子,如果先画满三个X就赢了。
比如
00 [00X00] 0000
这种情况下,下一个游戏者如果将“[]” 范围内的0 → X的话,就会输,所以就相当于每画一个X就把长条分为两个部分,就分成两个子问题,用sg 定理就可以
博弈题,主要还是求sg函数,找出状态 i 的所有后继状态,求出他的mex值。
数据比较小,所以不考虑找规律的问题,直接输出即可
AC代码:
#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
const int maxn = 2005;
int sg[maxn];
int vis[maxn];
//先利用sg函数找到规律
void init()
{
memset(sg,0,sizeof(sg));
//初始状态
sg[0] = 0;
sg[1] = 1;
sg[2] = 1;
for(int i = 2 ; i < maxn ;i++)
{
memset(vis,0,sizeof(vis));
//对于所有i状态,如果他的i-3/i-4/i-5状态是必败的话,那状态i就是必胜状态
vis[sg[i-3]] = 1;
vis[sg[i-4]] = 1;
vis[sg[i-5]] = 1;
for(int j = 0;j<= i-5;j++)
{
vis[sg[j]^sg[i-j-5]] = 1;
//对于每一种sg值都遍历一遍
}
for(int j = 0 ;;j++)
{
if(!vis[j])//找出后继状态中mex(sg[x]);
{
sg[i] =j;
break;
}
}
// if(sg[i]==0)
// cout<<"i:"<<i<<" sg[i]"<<sg[i]<<endl;
}
}
int main()
{
init();
//函数打印规律
int k;
int n;
while(cin>>n)
{
if(sg[n]==0)
cout<<"2"<<endl;
else
cout<<"1"<<endl;
}
return 0;
}