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 ...
随机推荐
- CTF反序列化wp(ciscn,nss,ctfshowweb入门)
[CISCN 2023 华北]ez_date 题目: <?php error_reporting(0); highlight_file(__FILE__); class date{ public ...
- Luban小试牛刀
Luban小试牛刀 LubanUnity LubanUnity配置工具配置解决方案 简介 Github 文档 视频教程 Unity工具 个人感觉挺强大,便捷的,适合中大型游戏项目的配置工作.小 ...
- Ajax分析与爬取实战
Ajax 分析与爬取实战 准备工作 安装好 Python3 了解 Python HTTP 请求库 requests 的基本用法 了解 Ajax 基础知识和分析 Ajax 的基本方法 爬取目标 以一个示 ...
- 使用selenium grid实现下发任务到远程机器,远程执行测试用例
背景: 1. UI自动化测试用例, 可能想要在不同版本.不同浏览器下执行 2. UI自动化测试用例较多的时候,耗时时间长,这个时候可以通过分散在不同的机器上执行,减少自动化测试时间 实现 通过sele ...
- NVIDIA Jetson AGX Xavier 从刷机之后到配置环境
特殊的配置环境需求: cuda-10.2.python 3.6.9.torch 1.7.0.torchversion 0.8.1,剩下的顺其自然即可(逃. 顺便说一句,里面的指令请一行一行仔细复制粘贴 ...
- 将PaddleOCR 转为 ONNX 运行
PaddleOCR 是目前最好的开源OCR框架, 但paddle框架的兼容性实在不怎么好, 部署的时候容易出现各种各样的问题. 如果能把PaddleOCR转成ONNX, 就可以跳过paddle框架坑的 ...
- Spring Cloud 比较
Spring Cloud 比较 一.简介 1.SpringCloud:一套微服务架构下的一站式解决方案,理念就是解决我们在微服务架构中遇到的任何问题: 2.SpringCloudAlibaba:阿里实 ...
- Vue3 之 computed 计算属性的使用与源码分析详细注释
目录 计算属性的基本用法 计算属性的源码 shared 工具方法抽离 计算属性的基本用法 computed 一般有两种常见的用法: 一:传入一个对象,内部有 set 和 get 方法,属于Comput ...
- [oeasy]python0010_怎么用命令行保存文件
编写 py 文件 回忆上次内容 上次 真的输出了 程序员的浪漫 Hello world! print函数 可以输出 字符串 但是 print这个词 别拼错 就连 大小写 也别能错 错了就改 也没事 ...
- oeasy教您玩转vim - 36 - # 插入字符
插入字符 回忆上节课内容 正则表达式 行头行尾 ^ 意味着行开头 $ 意味着行结尾 任意字符 . 代表任意字符 [a-z] 代表任意小写字母 字符数量 * 代表 0 到任意多个前字符 + 代表 1 ...