Game of CS 题解
前言
题意简述
Jolly 和 Emily 在玩一个游戏。游戏在一棵编号为 \([0, n-1]\) 的有根树上进行,根节点是 \(0\),每条边都有一个长度,初始所有边都没有颜色。
玩家只能经过没有被完全染色的边。在一次操作中,从根节点出发,在所能到达的边集中选择一条边,并将其染上 \(1\) 单位长度的颜色。不能进行染色的玩家则输掉这个游戏。
Emily 先手,假设他们都采取最优策略,请问谁会赢?
题目分析
公平游戏,考虑求 SG 函数,设 \(\operatorname{SG}(yzh)\) 表示以 \(yzh\) 为根的子树的 SG 函数。答案就是求 \(\operatorname{SG}(root)\)。
对于叶子节点 \(yzh\),后继状态是空集,有 \(\operatorname{SG}(yzh) = 0\)。
考虑非叶子节点 \(yzh\),对于她的每一个孩子 \(xym\),\(yzh\)、\(yzh\) 到 \(xym\) 的边和以 \(xym\) 为根的子树都能构成一棵树,求解这些树的 SG 函数是互不相关的子问题,所以 \(\operatorname{SG}(yzh)\) 便是这些子问题的 SG 函数的 Nim 和。
那么只需考虑往 \(xym\) 这一棵子树上加上其与 \(yzh\) 之间的边对 SG 函数的影响。设这条边的长度为 \(l\)。
当 \(l = 1\) 时,我们有子问题的 SG 函数值为 \(\operatorname{SG}(xym) + 1\)。考虑以下证明。
证明:
首先发现对于 \(\operatorname{SG}(xym) = k\) 等价于 \(xym\) 下面接了 \(k\) 条边权为 \(1\) 的边。因为类似 Nim 游戏,如果后手把 \(\operatorname{SG}(xym)\) 增加,那么先手一定有办法把 \(\operatorname{SG}(xym)\) 变回原来的值。所以操作后 \(\operatorname{SG}(xym)\) 只能减少,相当于在 \(k\) 条边中选一个位置截断。
所以在子问题基础上增加一条边,其 SG 函数值也会增加 \(1\)。
故结论成立。
接下来考虑 \(l > 1\) 的情况。经过手玩,容易发现规律。这里先给出结论:子问题 SG 函数值为 \(\operatorname{SG}(xym) \operatorname{xor} \left (l \bmod 2 \right )\)。以下是证明:
证明:
\(l = 2\) 时,归纳 \(\operatorname{SG}(xym)\),结论显然成立。
接下来假设 \(l = k - 1\) 时结论成立,其中 \(k \bmod 2 = 1\),下证 \(l = k\) 时结论成立。
对于 \(\operatorname{SG}(xym) = 0\) 时,显然成立。假设对于 \(\operatorname{SG}(xym) \leq p - 1\) 均成立,下证对于 \(\operatorname{SG}(xym) = p\) 成立。
先手若给这条边染色,则根据假设,后继局面的 SG 函数为 \(\operatorname{SG}(xym) \operatorname{xor} \left ((k - 1) \bmod 2 \right ) = \operatorname{SG}(xym)\)。
先手若改变 \(\operatorname{SG}(xym)\) 为 \(\operatorname{SG}(xym)' \in [0, \operatorname{SG}(xym) - 1]\)。根据假设,子问题的 SG 函数为 \(\operatorname{SG}(xym)' \operatorname{xor} 1\)。若 \(\operatorname{SG}(xym) \bmod 2=0\),\(\operatorname{SG}(xym)' \operatorname{xor} 1 \in [0, \operatorname{SG}(xym) - 1]\);反之,\(\operatorname{SG}(xym)' \operatorname{xor} 1 \in [0, \operatorname{SG}(xym) - 2] \cup \lbrace \operatorname{SG}(xym) \rbrace\)。
综合两种情况,若 \(\operatorname{SG}(xym) \bmod 2=0\),子问题 SG 函数值为 \(\operatorname{mex} \lbrace \operatorname{SG}(xym) \rbrace \cup [0, \operatorname{SG}(xym) - 1] = \operatorname{mex} [0, \operatorname{SG}(xym)] = \operatorname{SG}(xym) + 1\);反之,子问题 SG 函数值为 \(\operatorname{mex} \lbrace \operatorname{SG}(xym) \rbrace \cup [0, \operatorname{SG}(xym) - 2] \cup \lbrace \operatorname{SG}(xym) \rbrace = \operatorname{mex} [0, \operatorname{SG}(xym) - 2] = \operatorname{SG}(xym) - 1\)。
发现子问题的 SG 函数值恰好是 \(\operatorname{SG}(xym) \operatorname{xor} 1\)。故此时结论成立。
类似地,接下来假设 \(l = k - 1\) 时结论成立,其中 \(k \bmod 2 = 0\),下证 \(l = k\) 时结论成立。
对于 \(\operatorname{SG}(xym) = 0\) 时,显然成立。假设对于 \(\operatorname{SG}(xym) \leq p - 1\) 均成立,下证对于 \(\operatorname{SG}(xym) = p\) 成立。
先手若给这条边染色,则根据假设,后继局面的 SG 函数为 \(\operatorname{SG}(xym) \operatorname{xor} \left ((k - 1) \bmod 2 \right ) = \operatorname{SG}(xym) \operatorname{xor} 1\)。
先手若改变 \(\operatorname{SG}(xym)\) 为 \(\operatorname{SG}(xym)' \in [0, \operatorname{SG}(xym) - 1]\)。根据假设,子问题的 SG 函数为 \(\operatorname{SG}(xym)' \operatorname{xor} 0 = \operatorname{SG}(xym)'\)。
综合两种情况,无论 \(\operatorname{SG}(xym)\),子问题的 SG 函数值均为 \(\operatorname{SG}(xym)\),也即 \(\operatorname{SG}(xym) \operatorname{xor} 0\)。故结论成立。
综上所述,子问题 SG 函数值为 \(\operatorname{SG}(xym) \operatorname{xor} \left (l \bmod 2 \right )\) 对于所有 \(l \geq 2\) 均成立。证毕。
有了这般证明,代码使用一次深搜维护每个点的 SG 函数就行了。
代码实现
在洛谷上目前只有我一个人过,所以妥妥的 Rank1。
// #pragma GCC optimize(3)
// #pragma GCC optimize("Ofast", "inline", "-ffast-math")
// #pragma GCC target("avx", "sse2", "sse3", "sse4", "mmx")
#include <iostream>
#include <cstdio>
#define debug(a) cerr << "Line: " << __LINE__ << " " << #a << endl
#define print(a) cerr << #a << "=" << (a) << endl
#define file(a) freopen(#a".in", "r", stdin), freopen(#a".out", "w", stdout)
#define main Main(); signed main(){ return ios::sync_with_stdio(0), cin.tie(0), Main(); } signed Main
using namespace std;
#include <cstring>
#include <vector>
int cas, n, sg[1010];
vector<pair<int, int> > edge[1010];
void dfs(int now, int fa){
for (const auto & [to, len]: edge[now]) if (to != fa){
dfs(to, now);
if (len == 1) sg[now] ^= sg[to] + 1;
else sg[now] ^= sg[to] ^ (len & 1);
}
}
void solve() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) edge[i].clear(), sg[i] = 0;
for (int i = 1, u, v, w; i <= n - 1; ++i){
scanf("%d%d%d", &u, &v, &w), ++u, ++v;
edge[u].push_back(make_pair(v, w));
edge[v].push_back(make_pair(u, w));
}
dfs(1, 1314520736);
printf("Case %d: ", ++cas);
puts(sg[1] ? "Emily" : "Jolly");
}
signed main() {
int t; scanf("%d", &t);
while (t--) solve();
return 0;
}
Game of CS 题解的更多相关文章
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- JSOI Round 2题解
强行一波题解骗一个访问量好了... http://blog.csdn.net/yanqval/article/details/51457302 http://absi2011.is-programme ...
- 5059 一起去打CS
5059 一起去打CS 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 早就和lyk约好了去 ...
- 2017 google Round C APAC Test 题解
题解参考网上的答案,以及我自己的想法. 主要参考网站:http://codeforces.com/blog/entry/47181,http://codeforces.com/blog/entry/4 ...
- CS Round#53 C Histogram Partition
题意:给定一个数组A,以及一个初始值全为0的空数组B,每次可以对数组B的任意一个区间内的所有数+x,问至少几次操作能把B数组变成A数组 NOIP原题(积木大赛)升级版,话说CS怎么那么多跟NOIP原题 ...
- 2016广东工业大学新生杯决赛网络同步赛暨全国新生邀请赛 题解&源码
Problem A: pigofzhou的巧克力棒 Description 众所周知,pigofzhou有许多妹子.有一天,pigofzhou得到了一根巧克力棒,他想把这根巧克力棒分给他的妹子们.具体 ...
- 算法(第四版)C# 习题题解——3.1
写在前面 整个项目都托管在了 Github 上:https://github.com/ikesnowy/Algorithms-4th-Edition-in-Csharp 查找更方便的版本见:https ...
- 算法(第四版)C# 习题题解——2.5
写在前面 整个项目都托管在了 Github 上:https://github.com/ikesnowy/Algorithms-4th-Edition-in-Csharp 查找更方便的版本见:https ...
- 算法(第四版)C# 习题题解——2.4
写在前面 整个项目都托管在了 Github 上:https://github.com/ikesnowy/Algorithms-4th-Edition-in-Csharp 查找更方便的版本见:https ...
- 算法(第四版)C# 习题题解——2.3
写在前面 整个项目都托管在了 Github 上:https://github.com/ikesnowy/Algorithms-4th-Edition-in-Csharp 查找更为方便的版本见:http ...
随机推荐
- Java原子操作保证方案
引言 原子操作是指不会被线程调度机制打断的操作:这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程).通常所说的原子操作包括对非long和double ...
- EyeLink 1000 plus(桌面式)眼动仪使用指导
一.简介 眼动追踪是测量眼睛运行的过程.眼动追踪研究的最关注的事件是确定人类或者动物看的地方(比如:"注视点"或"凝视点").更准确来说是通过仪器设备进行图像处 ...
- 《最新出炉》系列入门篇-Python+Playwright自动化测试-52- 字符串操作 - 下篇
1.简介 在日常的自动化测试工作中进行断言的时候,我们可能经常遇到的场景.从一个字符串中找出一组数字或者其中的某些关键字,而不是将这一串字符串作为结果进行断言.这个时候就需要我们对字符串进行操作,宏哥 ...
- 高通与At指令:AtCop解析
背景 在某个新基线上移植AT指令,发现有问题,因此收集了这个系列的 文章 作为 这方面的知识补充. 原文作者:laozhuxinlu,本文有删改. 另外,还参考了:https://www.cnblog ...
- .net core 3.1 + 动态执行C#
1.使用 using Microsoft.CodeAnalysis.CSharp.Scripting;using Microsoft.CodeAnalysis.Scripting; 2.定义 Rosl ...
- 浅谈k8s中cni0和docker0的关系和区别
最近在复习k8s网络方面的知识,查看之前学习时整理的笔记和文档还有过往自己总结的博客之后发现一个问题,就是在有关flannel和calico这两个k8s网络插件的文章和博客中,会涉及到cni0和doc ...
- 3568F-物联网模块开发案例
- 实测952Mbps!四路千兆网PCIe拓展方案,国产工业级!
测试环境说明 运行系统:Debian-11.8 评估板:TL3588-EVM(RK3588J) 模块:PCIe扩展2/4路千兆网口模块 方案:无锡沐创N500L-AM2C-DD.N500L-AM4C- ...
- Basic_pentesting_1靶机渗透流程
Basic_pentesting_1 Description This is a small boot2root VM I created for my university's cyber secu ...
- ROS2开发BUG记录:在将 use_sim_timer 置为 true 时,节点的 Timer_Callback 行为“异常”
问题: 在将 use_sim_timer 置为 true 时,节点 Timer_Callback 行为 "异常" .在回调函数中,使用 self.get_logger().info ...