您的位置:首页 > 其它

【USACO Contest 】Holiday 2010 Bonus Competition, Problem 2: Rocks and Trees (rocks)

2010-08-18 15:13 323 查看
好不容易看懂了题。

     1            -         -         -
    / /          / /       / /       / /
   2   3        5   3     3   3     3   1

    图灵          图一      图二       图三

(图灵都出来了,我汗)

 

图二中先取者Ted不能获胜,是因为他在两个3里面移动任意一堆的x个石子,对手一定会在另一堆也移x个石子,继而使两堆的数量相同(或同为0,这样Ted就输了)。

 

然而图三中,Ted可以在左边的那个3个石子中移动2个,使两堆成为1跟1.,这样,对手只能移动其中一个1,Ted移动另一个1,就获胜了。

 

 

 

我是肉眼凡胎,只看出了树上深度相同的节点可以合并,最后合并成一条链,Ted是否能赢与石子深度的奇偶性有关系,但是没有发现这实质上是Nim取子游戏。(啊……这个contest要求数学知识渊博啊T_T,还得记性好,记住公式)(路人:你以为是啥,DP?)

 

 

[以下抄袭Analysis中的思路,我在考虑要不要把文章类型改为“翻译”]

 

树上的每个节点根据离根的距离(也就是深度(根的深度为0))的奇偶性分为奇节点与偶节点。

 

偶节点上的石子不要主动去移。当对手把偶节点的石子向奇节点移动x个时,Ted就可以把这x个石子再向根移动x个。这样,经过一阵沧桑后,所有偶节点的石子都将归于根节点。(于是凡是一个石子进了偶节点,就相当于进了一个归宿明确的黑洞,再也不能干扰奇节点的移动了。)

 

而奇节点上的石子,每次移动就是到了偶节点,也就是被偶节点“吃掉”了,我们不用管了。

 

于是,就成了Nim取子游戏,每个奇节点是一堆,没人每次在任意一堆中取走的石子数不超过L。

 

根据(没有每次取子上限的)Nim取子游戏公式(参见http://en.wikipedia.org/wiki/Nim),一共有N堆石子,每堆a[i]个,则当每个a[i]进行异或运算后等于0,则先取者有机会获胜。

 

在每次取子有上限L的情况下,公式类似,只是把每个a[i]换成a[i] mod (L+1),其余不变。

 

C++代码:

#include <fstream>
#include <iostream>
using namespace std;

int r[10001],odd[10001];

int main()
{
ifstream fin ("rocks.in");
ofstream fout ("rocks.out");
int i,n,t,l,x,y,p,win=0;

fin>>n>>t>>l;
l++;

for(i=2;i<=n;i++)
{
fin>>p>>r[i];
r[i]%=l;
if(odd[i]=!odd[p])win^=r[i];
}

for(i=0;i<t;i++)
{
fin>>x>>y;
y=y%l;
if(odd[x])win=win^r[x]^y;
r[x]=y;
fout<<(win?"Yes":"No")<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  2010 游戏 c