原题链接
①. 题目
②. 思路
Mex运算
- 设S表示一个非负整数集合.定义mex(S)为求出不属于集合S的最小非负整数运算,即:mes(S)=min{x};例如:S={0,1,2,4},那么mes(S)=3
SG函数:
- 在有向图游戏中,对于每个节点x,设从x出发共有k条有向边,分别到达节点y1,y2,····yk,定义SG(x)的后记节点y1,y2,····。yk的SG函数值构成的集合在执行mex运算的结果
SG(x)=mex({SG(y1),SG(y2)····SG(yk)})
。特别地,整个有向图游戏G的SG函数值被定义为有向图游戏起点s的SG函数值,即SG(G)=SG(s).
有向图游戏的和
- 有向图游戏的和的SG函数值等于它包含的各个子游戏SG函数的异或和,即:
SG(G)=SG(G1)xorSG(G2)xor···xor SG(Gm)
③. 学习点
博弈论
④. 代码实现
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;
public class Main {
static int M=110,N=10010,k;
static int s[]=new int[M];
static int sg[]=new int[N];
public static void main(String[] args) {
Arrays.fill(sg, -1);
Scanner sc = new Scanner(System.in);
k=sc.nextInt();
for (int i = 0; i <k; i++) {
s[i]=sc.nextInt();
}
int n=sc.nextInt();
int res=0;
while(n-->0) {
int x=sc.nextInt();
res^=sg(x);
}
System.out.println(res!=0?"Yes":"No");
}
static int sg(int x) {
if(sg[x]!=-1) return sg[x];
HashSet set = new HashSet<>();
for (int i = 0; i <k; i++) {
if(x>=s[i]) {
set.add(sg(x-s[i]));
}
}
for (int i = 0; i <=N; i++) {
if(!set.contains(i)) {
return sg[x]=i;
}
}
return 0;
}
}