博弈论+ybt题解
NIM游戏及其证明
题目描述即为T1,不多赘述
有向图游戏及SG函数
而对于由
当且仅当
考虑如何证明,我们考虑NIM游戏中一种合法的取法为选择一堆并取走其中任意大于0的石子数也就是可以从
我们考虑
同时有意思的一点是,NIM游戏也可以用SG函数来解释,我们有k堆相当于有k个起点,然后对于每个堆可以拿走任意个的限制就是对于
T1:
根据NIM游戏直接做
T2:
-
,那先手就不能进行操作,所以无必胜策略。 -
,先手有必胜策略。先手进行操作2,让后手陷入情况1。 -
若
是奇数( ),先手有必胜策略。先手进行操作1,因为一个数的本身也是它的因子,而且它是个奇数,所以可以除以它本身,让后手陷入情况1。 -
若
是偶数( ),偶数肯定不能进行操作2,因为偶-1=奇,让后手变成情况3,后手就赢了。
首先将
其中
4.1
因为
4.2
当
4.2.1.
则除完
4.2.2.
让后手陷入情况4.1,先手赢,有必胜策略。
4.3
也即:
4.3.1
此时只要除以
剩下
4.3.2.
除以
所以情况4.3都有必胜策略。
T3:
求SG函数练习题
首先我们把开始局面看成是一种状态,发现可以对于每一个
然后我们递归下去记搜SG函数即可,复杂度
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+5;
int n;
int a[N],sg[N];
int SG(int x){
if(sg[x]!=-1) return sg[x];
int k=0;
bool vis[x+50];\\注:这里vis只能为一个函数服务,所以要写在函数内部
memset(vis,0,sizeof(vis));
for(int i=1;i*i<=x;i++){
if(x%i) continue;
k^=SG(i);
if(i*i==x||i==1) continue;
k^=SG(x/i);
}
for(int i=1;i*i<=x;i++){
if(x%i) continue;
vis[k^SG(i)]=1;
if(i*i==x||i==1) continue;
vis[k^SG(x/i)]=1;
}
int res=0;
while(vis[res]) res++;
return sg[x]=res;
}
int main(){
memset(sg,-1,sizeof(sg));
sg[1]=0;
while(scanf("%d",&n)!=EOF){
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int k=0;
for(int i=1;i<=n;i++){
k^=SG(a[i]);
}
if(k!=0) printf("freda\n");
else printf("rainbow\n");
}
return 0;
}
T4:
硬控我一整天!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
思路很清晰明了,记忆化搜索出SG函数
本人问题:
1.为什么不可以直接把胜负反过来做?
因为考虑SG定理的证明,一个是任意一个是存在,反过来就不行了
2.为什么不可以设
起始状态不可设为1,不满足定理
3.1*1为什么不可以看成一个必败状态,直接进行转移?
待解答ing。。。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探