标签:函数 over else 证明 判断 sdn 移动 article line
关于Nim游戏,sg函数及其一些变形可以戳这位大佬的blog:
https://blog.csdn.net/clover_hxy/article/details/53818624
这是一道阶梯Nim游戏的题,与普通的阶梯Nim游戏不同之处在于它是在一棵树上移动,实际上就是多个阶梯Nim游戏的复合
我们知道,阶梯Nim游戏可以视作对奇数阶梯上上的石子做Nim,证明在上方的blog中有提及,在此不再赘述
在此题中,设\(1\)号节点的深度为\(0\),那么深度为奇数的节点即为“奇数阶梯”
考虑每次对节点上石头数量的修改,我们可以保存上一次修改后求出的\(sg\)值的异或和\(x\)
如果修改的节点的深度为偶数,对答案并没有贡献,直接判断上一次的\(x\)即可
如果修改的节点的深度为奇数,由于异或满足自反性(即\(x\) xor \(x\) \(=0\)),所以在修改之前,我们只需要对\(x\)异或一遍修改前的数,再异或一遍修改后的数即可,而没有必要重新求一遍异或和
#include <cstdio>
#define maxn 10005
#define maxL 1005
using namespace std;
int n,T,L;
int r[maxn],prt[maxn],dep[maxn];
int sg[maxL];
int x;
inline bool Solve(int pos,int chg)
{
if(!(dep[pos]&1))
return x;
x^=sg[r[pos]];
x^=sg[r[pos]=chg];
return x;
}
int main()
{
scanf("%d%d%d",&n,&T,&L);
register int i;
int a,b;
for(i=1;i<=1000;++i)
sg[i]=i%(L+1);
for(i=2;i<=n;++i)
{
scanf("%d%d",&prt[i],&r[i]);
dep[i]=dep[prt[i]]+1;
if(dep[i]&1)
x^=sg[r[i]];
}
for(i=1;i<=T;++i)
{
scanf("%d%d",&a,&b);
if(Solve(a,b))
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
【题解】Luogu P2972 [USACO10HOL]岩石和树木Rocks and Trees
标签:函数 over else 证明 判断 sdn 移动 article line
原文地址:https://www.cnblogs.com/lizbaka/p/10246414.html