CodeForces Round #417 E Solution:Nim博弈
来源:互联网 发布:网页信息采集软件 编辑:程序博客网 时间:2024/06/14 20:45
第一次做博弈相关的题目,所以写的比较详细。
题意:给出一棵树,数据保证根为1号点,每个点上有一些石子,树的形态保证:根到每个叶子结点的路径长度奇偶性相同,也就是说叶子结点的深度彼此相差2或者4或者6等等。
博弈规则:选取任意非0的点,如果是叶子结点,那么取出任意多个石子吃掉;如果不是叶子节点,取出任意多个石子加到一个孩子上去,首先出现无法操作的人输。
题解:这是典型的Nim博弈,那么关键在于SG函数的求解。
按照一般思路:先找terminal position,显然terminal position是整个树一个石子也不剩的情况。
往前推一步得到一些N position,那么显然,只有一个非0叶子节点是N position
继续想:如果只有叶子结点非0,那么就转化为经典的Nim石子博弈,当抑或和!=0的时候是N position,反之是P position。
在深入想:如果现在有非0的叶子节点,也有非0的高度为1的节点(叶子结点高度为0)。那么无论上一层是什么情况,胜负手只取决于叶子这一层:如果叶子层抑或和是0,就是P position 否则就是N position(必胜),因为如果叶子节点抑或和不是0,那么我可以吃掉叶子来达到Nim平衡,而对方无论是下放石子还是吃掉石子都会破坏Nim平衡,所以我是必胜的。相反如果抑或和是0,我只能打破Nim平衡,则对方必胜。
现在思路渐渐清晰了,和叶子节点的deep奇偶性相同的节点我们叫他 偶数层节点,其他的叫做 奇数层节点的话,如果我偶数层节点有Nim平衡的话,那么我的任何操作都会破坏这个平衡,然后对手永远都可以恢复这个平衡,随着石子不断下放,只剩下叶子这一层的时候,转化为最最经典的Nim博弈,则我是必输的。相反,如果偶数层节点没有Nim平衡,那么我必有方法恢复Nim平衡,使得对手被迫破坏Nim平衡,同理,我必胜。
现在分析得知:先遍历一次树,计算好每个点的deep,把偶数层节点的抑或和算出来,如果是0先手必败,否则先手必胜。题目要求允许你做一次交换,交换任意不同两点的石子数,问有多少种交换方式使得后手必胜。(u,v)和(v,u)算作一种。
剩下的就是一个trick了,如果我们算出来的抑或和K!=0,那么说明后手必败,必须在偶数层和奇数层之间做交换,才可能使得K==0,假设交换的偶数层的那个点石子数是a,奇数层的是b,那么交换之后的新的K等于K^b^a=0于是简单变形就是:K^a=b,那么我们可以这么做:在遍历的时候,每个偶数层的点,把他扔进一个Vector里面,每个奇数层的点我们开一个桶统计一下出现次数。然后对每个vector里面的元素x,我们让ans+=count[ K^( x ) ]就好了。
如果我们算出来的抑或和K==0,那么我们允许三种交换:偶数层任意两个点做交换,奇数层任意两个点做交换,偶数层和奇数层相同的点之间做交换,我们发现最后一种情况直接用上边的方法就行了。然后再加两次答案就好了。
AC代码:
#include<bits/stdc++.h>using namespace std;int can[17000005];vector<int> a;int father[100005];int n;bool leaf[100005];int que[1000000];int deep[100005];int aa[100005];int main(){ cin>>n; memset(leaf,true,sizeof(leaf)); for (int i=1;i<=n;i++){ scanf("%d",&aa[i]); } for (int i=2;i<=n;i++){ scanf("%d",&father[i]); leaf[father[i]]=false; } int l=0; int r=0; for (int i=1;i<=n;i++){ if (leaf[i]){ r++; que[r]=i; } } while (l<r){ l++; int q=que[l]; if (deep[father[q]]==0&&q!=1){ r++; deep[father[q]]=deep[q]+1; que[r]=father[q]; } } int k=0; for (int i=1;i<=n;i++){ if ((deep[i]&1)==0){ k^=aa[i]; a.push_back(aa[i]); }else{ can[aa[i]]++; } } long long ans=0; if (k==0){ long long temp = a.size(); ans+=(temp*(temp-1))/2; temp = n-temp; ans+=(temp*(temp-1))/2; } for (vector<int>::iterator it = a.begin();it!=a.end();it++){ ans+=can[k^(*it)]; } cout<<ans<<endl; return 0;}
- CodeForces Round #417 E Solution:Nim博弈
- CodeForces 768E Game of Stones (Nim博弈)
- [博弈 杂题] Codeforces 794E Round #414 E. Choosing Carrot
- Codeforces Round #266 (Div. 2) Problem E Solution
- Codeforces Round #417:E. FountainsSagheer and Apple Tree(树上博弈)
- Codeforces Round #417:E. FountainsSagheer and Apple Tree(树上博弈)
- Codeforces Round #417 (Div. 2) E. Sagheer and Apple Tree (树上尼姆博弈)
- Codeforces Round #399 E Game of Stones 博弈
- codeforces 15C Industrial Nim(NIM 博弈)
- CodeForces 827E Round$423 Div1E Solution:暴力的正确姿势
- codeforces round#177 E
- Codeforces Round#260E
- CodeForces 15C Industrial Nim (博弈)
- Codeforces 15C Industrial Nim 简单博弈
- Codeforces Round #228 (Div. 2) E Fox and Card Game(贪心博弈)
- 解题报告:Codeforces Round #432 (Div. 2) E.Arpa and a game with Mojtaba (博弈)
- Codeforces Round #432 (Div. 2) (Codeforces 850C) E. Arpa and a game with Mojtaba 博弈+状态压缩
- Codeforces Round #269 (Div. 2) Solution
- 剑指offer-24-二叉树中和为某一值的序列
- 结构体指针
- 【LeetCode】283.Move Zeroes解题报告
- 59 C语言循环结构的嵌套
- Linux中的poll机制
- CodeForces Round #417 E Solution:Nim博弈
- Spring_JSR 303标准的校验框架与SpringMVC际化、及校验字符串消息国际化
- UVa 1471 Defense Lines——LIS nlogn 算法变形
- CentOS 7 安装VirtualBox
- at24c08 E2PROM的I2C设备驱动实例——基于mini2440
- 端午节月赛-山东省第八届省赛 quadratic equation(多种情况,△的判断)
- 发送有序广播
- POJ2533 Longest Ordered Subsequence【最长上升子序列+DP】
- USACO 3.3.1 骑马修栅栏