AcWing----893. 集合-Nim游戏(Java)_数学知识_博弈论_SG函数_Mex运算_N图

原题链接

①. 题目

在这里插入图片描述

②. 思路

在这里插入图片描述

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]; //存放某个数的SG函数的值
	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();
			//直接异或sg函数的和 进行判断
			res^=sg(x);
		}
		System.out.println(res!=0?"Yes":"No");
	}
	
	//递归sg 有点难搞 debug看看
	static int sg(int x) {
    
    
		if(sg[x]!=-1) return sg[x]; //若sg存在直接返回出来
		//每次递归重新创建一个set集合
		HashSet set = new HashSet<>();
		//枚举集合中每一个数 进行比较
		for (int i = 0; i <k; i++) {
    
    
			if(x>=s[i]) {
    
    
				set.add(sg(x-s[i])); //递归往set集合中添加sg函数
			}
		}
		//在集合中找,最小的不存在的值
		for (int i = 0; i <=N; i++) {
    
    
			if(!set.contains(i)) {
    
    
				return sg[x]=i;//找到,保存,返回
			}
		}
		return 0;
	}
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45480785/article/details/114105054