SG 函数

news/2025/10/21 16:45:11/文章来源:https://www.cnblogs.com/xiaoxiongtaotao/p/19155815

模型介绍

SG 函数是组合博弈论中的核心工具,用于分析公平组合博弈(Impartial Games)。它提供了一个统一的框架,将各种博弈问题转化为 Nim 游戏的形式。

基本概念:

  • 公平组合博弈:两个玩家、完全信息、无随机因素、有限步结束;
  • 每个游戏状态都有一个 SG 值;
  • 终局状态的 SG 值为 \(0\)
  • 其他状态的 SG 值由其后续状态的 SG 值决定。

历史背景

SG 函数由 R.P. Sprague(\(1935\))和 P.M. Grundy(\(1939\))独立发现,因此得名 Sprague-Grundy 函数。他们的工作建立了组合博弈论的数学基础,证明了任何公平组合博弈都等价于某个 Nim 堆。

核心定义与证明

SG 函数定义

对于一个游戏状态x,其SG函数值定义为:

\[SG(x)=mex\{SG(y)\} \]

其中 mex(minimum excludant)表示最小的不属于该集合的非负整数。

Sprague-Grundy 定理

  • 定理:任何公平组合博弈都等价于一个 Nim 堆,其大小为该博弈的 SG 值。
  • 证明思路:
  1. 基础情况:终止状态的 SG 值为 \(0\),等价于大小为 \(0\) 的 Nim 堆;
  2. 归纳假设:假设所有后续状态都等价于 Nim 堆;
  3. 关键观察:从状态 \(x\) 可以移动到 SG 值为 \(0,1,...,SG(x)-1\) 的任何状态;但不能移动到 SG 值为 \(SG(x)\) 的状态;这与大小为 \(SG(x)\) 的 Nim 堆的行为完全一致;
  4. 组合博弈:多个独立游戏的组合的 SG 值等于各游戏 SG 值的异或和。

详细证明

  1. 引理 \(1\)\(SG(x)=0\) 当且仅当 \(x\) 是必败态,证明:
  • 如果 \(SG(x)=0\),则没有 \(SG=0\) 的后继状态,即所有移动都到必胜态;
  • 如果 \(SG(x)\neq0\),则存在移动到 \(SG=0\) 状态的移动。

定理证明:

考虑游戏 G,其 SG 值为 \(g\)。我们证明 G 等价于大小为 \(g\) 的 Nim 堆。

  1. 从状态G可以移动到任何 SG 值小于 \(g\) 的状态(由 \(mex\) 定义);
  2. 从大小为 \(g\) 的 Nim 堆可以移动到任何小于 \(g\) 的大小;
  3. 两者具有完全相同的移动可能性。

因此,\(G\cong Nim(g)\),对于组合游戏 \(G_1+G_2+\cdots+G_n\)

\[SG(G_1+G_2+\cdots+G_n)=SG(G_1)\oplus SG(G_2)\oplus\cdots\oplus SG(G_n) \]

代码实现

基础 SG 函数计算

#include <bits/stdc++.h>
#define int long longusing namespace std;// 计算mex函数
int mex(const set<int>& values) {int result = 0;while (values.find(result) != values.end()) {result++;}return result;
}// 通用的SG函数计算框架
class SGFunction {private:vector<int> sg_values;vector<vector<int>> moves;  // moves[i] 表示从状态i可以移动到的状态public:SGFunction(int max_state, const vector<vector<int>>& move_rules): sg_values(max_state + 1, -1), moves(move_rules) {}// 计算状态state的SG值int calculateSG(int state) {if (sg_values[state] != -1) {return sg_values[state];}if (isTerminal(state)) {return sg_values[state] = 0;}set<int> successor_sg;for (int next_state : getMoves(state)) {successor_sg.insert(calculateSG(next_state));}return sg_values[state] = mex(successor_sg);}// 判断是否为终止状态(需要根据具体游戏实现)bool isTerminal(int state) {// 基础实现:状态0为终止状态return state == 0;}// 获取从state可以移动到的状态(需要根据具体游戏实现)vector<int> getMoves(int state) {if (state < moves.size()) {return moves[state];}return {};}// 判断组合游戏是否先手必胜bool isWinningPosition(const vector<int>& states) {int xor_sum = 0;for (int state : states) {xor_sum ^= calculateSG(state);}return xor_sum != 0;}
};

具体游戏示例:取石子游戏

// 取石子游戏的SG函数实现
class TakeStonesGame {private:vector<int> sg;vector<int> allowed_moves;public:TakeStonesGame(int max_stones, const vector<int>& moves): sg(max_stones + 1, -1), allowed_moves(moves) {sort(allowed_moves.begin(), allowed_moves.end());}int calculateSG(int stones) {if (sg[stones] != -1) return sg[stones];if (stones == 0) return sg[stones] = 0;set<int> successor_sg;for (int take : allowed_moves) {if (take <= stones) {successor_sg.insert(calculateSG(stones - take));}}return sg[stones] = mex(successor_sg);}void analyzeGame(int max_stones) {cout << "SG值分析 (允许取: ";for (int move : allowed_moves) cout << move << " ";cout << ")" << endl;for (int i = 0; i <= max_stones; i++) {cout << "SG(" << i << ") = " << calculateSG(i) << endl;}cout << endl;// 分析周期模式findPeriod();}private:void findPeriod() {cout << "寻找周期模式..." << endl;int start = 10;  // 从第10个状态开始寻找周期int period = 0;for (int p = 1; p <= 20; p++) {bool is_periodic = true;for (int i = start; i < start + p && i + p < sg.size(); i++) {if (sg[i] != sg[i + p]) {is_periodic = false;break;}}if (is_periodic) {period = p;break;}}if (period > 0) {cout << "发现周期: " << period << endl;} else {cout << "未发现明显周期" << endl;}}
};

变种题目与解法

变种 1:多堆取石子游戏

  • 问题:有 \(n\) 堆石子,每堆 \(a_i\) 个,每次可以从一堆中取 \(f(k)\) 个(\(f\) 是给定的函数);
  • 解法:计算每堆的 SG 值,然后求异或和。
class MultiPileGame {private:vector<int> sg;function<int(int)> move_function;public:MultiPileGame(int max_stones, function<int(int)> func): sg(max_stones + 1, -1), move_function(func) {}int calculateSG(int stones) {if (sg[stones] != -1) return sg[stones];if (stones == 0) return sg[stones] = 0;set<int> moves;int k = 1;while (true) {int take = move_function(k);if (take > stones) break;moves.insert(calculateSG(stones - take));k++;}return sg[stones] = mex(moves);}bool canWin(const vector<int>& piles) {int xor_sum = 0;for (int pile : piles) {xor_sum ^= calculateSG(pile);}return xor_sum != 0;}
};

变种 2:图游戏

  • 问题:在图上移动棋子,每次沿边移动,无法移动者输;
  • 解法:使用记忆化搜索计算每个节点的 SG 值。
class GraphGame {private:vector<vector<int>> graph;vector<int> sg_values;public:GraphGame(int n, const vector<vector<int>>& adj_list): graph(adj_list), sg_values(n, -1) {}int calculateSG(int node) {if (sg_values[node] != -1) return sg_values[node];set<int> successor_sg;for (int neighbor : graph[node]) {successor_sg.insert(calculateSG(neighbor));}return sg_values[node] = mex(successor_sg);}// 在多个棋子的情况下判断胜负bool canWin(const vector<int>& positions) {int xor_sum = 0;for (int pos : positions) {xor_sum ^= calculateSG(pos);}return xor_sum != 0;}
};

变种 3:减法游戏

  • 问题:每次只能取特定数量的石子;
  • 解法:预计算 SG 值表。
class SubtractionGame {private:vector<int> sg;vector<int> allowed_moves;public:SubtractionGame(int max_n, const vector<int>& moves): sg(max_n + 1, -1), allowed_moves(moves) {}int calculateSG(int n) {if (sg[n] != -1) return sg[n];if (n == 0) return sg[n] = 0;set<int> values;for (int move : allowed_moves) {if (move <= n) {values.insert(calculateSG(n - move));}}return sg[n] = mex(values);}void printSGTable(int up_to) {cout << "n\tSG(n)" << endl;for (int i = 0; i <= up_to; i++) {cout << i << "\t" << calculateSG(i) << endl;}}
};

变种 4:翻硬币游戏

  • 问题:一排硬币,每次翻转连续的 \(k\) 个硬币,最后无法操作者输;
  • 解法:将游戏分解为子游戏。
class CoinFlipGame {private:vector<int> sg;int flip_length;public:CoinFlipGame(int max_coins, int k) : sg(max_coins + 1, -1), flip_length(k) {}int calculateSG(int n) {if (sg[n] != -1) return sg[n];if (n < flip_length) return sg[n] = 0;set<int> values;for (int i = 0; i <= n - flip_length; i++) {// 翻转操作将游戏分成两个独立的子游戏values.insert(calculateSG(i) ^ calculateSG(n - flip_length - i));}return sg[n] = mex(values);}
};

总结

SG 函数的重要性:

  1. 统一框架:将各种公平组合博弈统一到 Nim 游戏
  2. 组合性质:多个独立游戏的组合的 SG 值简单异或即可
  3. 算法效率:通过记忆化搜索高效计算复杂博弈
  4. 理论深度:连接了博弈论、组合数学和计算机科学

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/942425.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025 年铝包木阳光房生产厂家最新推荐榜:口碑至上的实力品牌甄选及选购指南

引言 在绿色建筑理念深化与消费升级的双重驱动下,铝包木阳光房凭借实木的温润质感与铝合金的耐用特性,成为中高端家装与工装市场的优选品类。但当前市场呈现 “老牌林立、新牌涌现” 的格局,数百个品牌混杂其中,部…

AI智能体是加速器,而非开发者替代品

将AI集成到应用开发中的核心挑战,不在于其协助能力,而在于我们能在多大程度上放心地将控制权委托给它。尽管AI智能体可以完美地执行那些曾被认为人类专属的任务,但它们同样可能在紧接着的下一段代码中犯下令人震惊的…

2025年兄弟机床维修厂家权威推荐榜:专业维修技术与高效服务口碑深度解析

2025年兄弟机床维修厂家权威推荐榜:专业维修技术与高效服务口碑深度解析 行业背景与发展现状 随着制造业数字化转型的深入推进,数控机床作为现代工业生产的核心装备,其稳定运行直接关系到企业的生产效率和产品质量。…

VUE中表达校验-明明有值却还是出现非空提示

VUE中表达校验-明明有值却还是出现非空提示1 说明对原先的一个表单编辑功能进行修改,有两个选择框从非必填变为必填。修改完成后,去编辑的时候有时候就会出问题,明明选择了值,却还是出现非空提示2 代码其中,机构部…

Oracle统计信息相关

以下是检查 Oracle 统计信息更新时间的常用方法: 1. 查看表级统计信息更新时间 -- 查看用户表统计信息 SELECT table_name, num_rows,last_analyzed,TO_CHAR(last_analyzed, YYYY-MM-DD HH24:MI:SS) as analyze_time,…

2025年栏杆护栏厂家权威推荐榜:不锈钢栏杆、桥梁防撞护栏、河道景观护栏,专业制造与工程应用深度解析

2025年栏杆护栏厂家权威推荐榜:不锈钢栏杆、桥梁防撞护栏、河道景观护栏,专业制造与工程应用深度解析 行业背景与发展趋势 随着城市化进程加速和基础设施建设不断完善,栏杆护栏行业迎来了新的发展机遇。作为公共安全…

Consul 与 Prometheus 集成实战:服务自动发现与监控配置指南(含 ThinkPHP8 示例)

Consul 与 Prometheus 集成实战:服务自动发现与监控配置指南(含 ThinkPHP8 示例)本文详细讲解 Consul 与 Prometheus 的集成方案,解决传统 Prometheus 监控需手动配置 Target 的繁琐问题。核心借助 Consul 的服务注…

完整教程:笔记本键盘失灵别慌!3种方法快速禁用(附恢复技巧)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025年工业设备安装厂家权威推荐榜:管道/电气/暖通空调/空压系统/纯水系统/厂房通风/车间配电/机械设备安装服务深度解析

2025年工业设备安装厂家权威推荐榜:管道/电气/暖通空调/空压系统/纯水系统/厂房通风/车间配电/机械设备安装服务深度解析 工业设备安装行业发展趋势 随着制造业转型升级步伐加快,工业设备安装行业正迎来新一轮发展机…

阿里云微服务引擎 MSE 及 API 网关 2025 年 9 月产品动态

阿里云微服务引擎 MSE 及 API 网关 2025 年 9 月产品动态

2025 年最新防伪溯源服务商权威推荐榜单:AI 技术赋能 + 软硬件一体优选指南及品牌选择攻略防伪溯源标签/AI防伪溯源/防伪溯源数字标签推荐

引言 在当前市场环境下,假冒伪劣产品依旧肆虐,从食品药品到电子数码,多个行业深受其害,不仅严重侵害消费者合法权益,更让正规企业面临品牌信誉受损、经济损失惨重的困境。传统防伪技术因静态化、易仿制的短板,已…

题解:P1196 [NOI2002] 银河英雄传说

P1196 [NOI2002] 银河英雄传说 这是一道绿题 核心考察点只有一个: 那就是带权并查集\(\mathcal{Part\ I}\) 我们检查题意不难发现这道题的要求无非两个: $\ \ $ 1 ) 维护多个链的不断合并,但是以链中某节点作为索引…

配置即权限:从传统开源 RBAC 框架到 SPARK 的六层资料护盾,告别改权限就要改代码的魔咒

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025年TYPE-C母座厂家权威推荐榜:防水/板上/沉板/立插/卧式/侧贴/贴片式/插件式全系列,5A大电流高速TID认证接口一站式供应

2025年TYPE-C母座厂家权威推荐榜:防水/板上/沉板/立插/卧式/侧贴/贴片式/插件式全系列,5A大电流高速TID认证接口一站式供应 随着电子设备向轻薄化、多功能化方向发展,TYPE-C接口凭借其正反插拔、高速传输和大功率充…

Oracle下查询数据库SQL ID

以下是常用查询SQLID的方法: 1. 通过 V$SQL 视图查询(常用) -- 根据SQL文本模糊查询SQLID SELECT sql_id, sql_text, executions, elapsed_time/1000000/executions as avg_elapsed_sec FROM v$sql WHERE sql_text …

深入解析:【数据结构】顺序表0基础知识讲解 + 实战演练

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025年流量控制阀厂家推荐排行榜,液压流量控制阀,气动流量控制阀,高压流量控制阀,精密流量控制阀批发公司推荐

2025年流量控制阀厂家推荐排行榜:液压、气动与高压精密控制技术深度解析 在工业自动化与过程控制领域,流量控制阀作为关键执行元件,其性能直接影响整个系统的稳定性与效率。随着工业4.0和智能制造的深入推进,流量控…

楼里网站开发完成,产品进入交代期

在产品一期的过程中手忙脚乱,到产品二期已经从从容容游刃有余,要做的事情还有不少,走一步算一步。👏 哈喽大家好,在安静了一段时间之后,楼里产品系列二期,于2025年10月21日正式收尾。 ✅ 开发的时间周期不到一…

比特币挖矿盈利能力9月下降超7%

根据某投资机构报告,9月份比特币挖矿盈利能力下降超过7%,主要原因是网络算力上升和比特币价格下跌。北美上市矿企产量降至3401枚比特币,每EH/s收入从8月的5.6万美元降至5.2万美元。比特币挖矿盈利能力9月下降超7% 核…

LobeHub UI Kit

LobeHub UI Kit 漫思