📜  组合博弈论 | Set 3 (Grundy NumbersNumbers and Mex)(1)

📅  最后修改于: 2023-12-03 14:56:50.715000             🧑  作者: Mango

组合博弈论 | Set 3 (Grundy NumbersNumbers and Mex)

组合博弈论是博弈论的一种分支,主要研究的是组合游戏的理论和方法。其中,Grundy数和Mex运算是两个重要的概念。

Grundy数

Grundy数是用来描述一个组合游戏的状态的一种数字,并且用来计算必胜策略。在组合游戏中,每个状态都有一个对应的Grundy数。Grundy数的计算是通过对状态的后继状态的Grundy数值进行异或操作(即先求出所有后继状态的Grundy数,然后取出所有未出现的最小非负整数作为该状态的Grundy数)来计算的。

例如,一个游戏中的初始状态的Grundy数为0,那么如果该状态有两个后继状态的Grundy数分别为2和3,那么该状态的Grundy数就为1。如果一个状态的所有后继状态的Grundy数都已经出现过了,那么该状态的Grundy数就为最小的未出现的非负整数。这个最小未出现的非负整数被称为这个状态的mex值。

Mex运算

Mex运算,也称为取未出现过的最小非负整数,是用来计算Grundy数的。在一个集合中,如果有连续的k个自然数都不在集合中出现,则集合的mex为k。集合mex的值也被称为该集合的Grundy数。

在计算Grundy数时,我们需要计算一个集合中所有元素的mex值,然后取其异或和作为这个集合的Grundy数。

代码示例

下面是一个求Grundy数的示例程序。该程序使用Python编写,将两个集合合并成一个集合,然后求出这个集合的Grundy数,并输出结果。

def calculate_grundy(A, B):
    """
    计算两个集合合并后的Grundy数
    :param A: 集合1
    :param B: 集合2
    :return: Grundy数
    """

    # 将两个集合合并成一个集合
    s = set(A) | set(B)

    # 计算集合中所有元素的mex值
    mex_values = []
    for i in range(len(s)):
        mex = 0
        while mex in s:
            mex += 1
        mex_values.append(mex)

    # 取异或和作为Grundy数
    grundy = mex_values[0]
    for i in range(1, len(mex_values)):
        grundy ^= mex_values[i]

    return grundy

# 示例
A = [3, 4, 5, 6]
B = [1, 2, 7, 8]
grundy = calculate_grundy(A, B)
print(grundy)

输出结果为:0。这说明合并后的集合的Grundy数为0,即先手必输。