S-Nim
应该是最板的一道题了 q w q qwq qwq。
把 k k k堆石子的博弈分解成 k k k个子问题再把它们的 SG \text{SG} SG 函数值异或起来, s g [ i ] sg[i] sg[i]表示 i i i个石子的 SG \text{SG} SG 函数值,记忆化搜索即可,注意:搜索过程中算 m e x mex mex时 v i s vis vis的大小就是操作集合的大小。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int M = 10005;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n,m,k,f[105],sg[M];
int get(int x)
{
if(x==0) return 0;
if(sg[x]!=-1) return sg[x];
bool vis[105]={};
for(int i=1;i<=n && f[i]<=x;i++)
vis[get(x-f[i])]=1;
for(int i=0;;i++)
if(!vis[i])
return sg[x]=i;
}
int main()
{
while(~scanf("%d",&n) && n)
{
memset(sg,-1,sizeof sg);
for(int i=1;i<=n;i++)
f[i]=read();
sort(f+1,f+1+n);
m=read();
while(m--)
{
k=read();
int flag=0;
for(int i=1;i<=k;i++)
flag^=get(read());
if(flag) putchar('W');
else putchar('L');
}
puts("");
}
}
A New Tetris Game(2)
很暴力的一道题了,我们直接把图搞成字符串然后拿去跑 SG \text{SG} SG函数。
注意每一行后面要插入一个特殊字符,复杂度就别问我了(你觉得我算的出来吗? ),感性理解,状态数不会很多 ,然后就贴一个我的代码。
#include <cstdio>
#include <iostream>
#include <map>
using namespace std;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n,r,c;char g[55][55];
map<string,int> sg;
string _str()
{
string s;
for(int i=0;i<r;i++)
{
s+=g[i];
s+='*';
}
return s;
}
int get()
{
string x=_str();
if(sg.count(x)) return sg[x];
int vis[55]={};
for(int i=1;i<r;i++)
for(int j=1;j<c;j++)
if(g[i][j]=='0' && g[i-1][j]=='0' && g[i][j-1]=='0' && g[i-1][j-1]=='0')
{
g[i][j]=g[i-1][j]=g[i][j-1]=g[i-1][j-1]='1';
vis[get()]=1;
g[i][j]=g[i-1][j]=g[i][j-1]=g[i-1][j-1]='0';
}
for(int i=0;;i++)
if(!vis[i])
return sg[x]=i;
}
int main()
{
while(~scanf("%d",&n))
{
int flag=0;
while(n--)
{
r=read();c=read();
for(int i=0;i<r;i++) scanf("%s",g[i]);
flag^=get();
}
if(flag) puts("Yes");
else puts("No");
}
}
Nim游戏(hihocoder)
还是把原问题
n
n
n个子问题,考虑
SG
\text{SG}
SG函数,设
s
g
[
i
]
sg[i]
sg[i]为
i
i
i堆石子的
SG
\text{SG}
SG函数值,转移如下:
s
g
[
i
]
=
m
e
x
{
s
g
[
j
]
,
s
g
[
j
]
⊕
s
g
[
j
−
i
]
}
sg[i]=mex\{sg[j],sg[j]\oplus sg[j-i]\}
sg[i]=mex{sg[j],sg[j]⊕sg[j−i]}然后就是打表找规律下面给出我打的表:
k 0 1 2 3 4 5 6 7 8 9 10 11 12 …
sg(k) 0 1 2 4 3 5 6 8 7 9 10 12 11 …
规律很容易看出来,贴个代码 q w q qwq qwq。
#include <cstdio>
int read()
{
int x=0,flag=1;
char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n,ans;
int main()
{
n=read();
for(int i=1;i<=n;i++)
{
int x=read();
if(x%4==3) x++;
else if(x%4==0) x--;
ans^=x;
}
if(ans) puts("Alice");
else puts("Bob");
}