acwing894. 拆分-Nim游戏
acwing894. 拆分-Nim游戏
原题链接:https://www.acwing.com/problem/content/896/
思路
取走一堆放入两堆,好像总的堆数一直在增加,但是每次放入的两堆各堆的数量一定小于取走的那一堆的数量,可能到最后每次放入的两堆的数量都是0,所以是有终点的。
此题将每一堆石子看成独立的局面
将每堆石子看做独立的局面,即个有向图游戏。
然后求每个局面的SG函数,,求其异或和
则先手必胜
则先手必败
对于每一个有向图都存在如下情况:拿走,增加了两堆石子,根据SG定理,
代码
#include<iostream>
#include<cstring>
#include<unordered_set>
using namespace std;
const int N = 110;
int f[N],a[N];
int n;
int SG(int x)
{
// 如果已经计算过SG函数值的直接返回
if(f[x] != -1) return f[x];
unordered_set<int> S; // 记录这个图x中的所有SG函数值
// 遍历所有可能
for(int i = 0; i < x; i ++)
for(int j = 0; j <= i; j ++) // 这里可以取等,遍历到i就行,因为会有重复
S.insert(SG(i)^SG(j));
// mex
for(int i = 0;; i ++)
{
if(!S.count(i)) return f[x] = i;
}
}
int main()
{
cin >> n;
for(int i = 0; i < n; i ++) cin >> a[i];
memset(f,-1,sizeof f);
int res = 0;
for(int i = 0; i < n; i ++)
res ^= SG(a[i]);
if(res) puts("Yes");
else puts("No");
return 0;
}
rds_blogs
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】