魔法游戏 - 博弈论

题目大意:
给一颗树,每个位置有一个权值,每次一个人可以选择森林中的某棵树的根节点,设其权值为 a a ,那么这个人可以选择一个 k [ 2 , a + 1 ] k\in[2,a+1] ,然后让 a a 变成 a k \left\lfloor\frac ak\right\rfloor 。如果一个点权值变为0那么就把这个点删除。不能操作者输,问谁赢。
题解:
考虑一个权值的二进制位,那么每次一个点的二进制位数会至少减1至多变成0。那么一颗树的sg就很好确定了。(其实直接暴力也可以不过没什么必要就直接写的简单了些。

#include<bits/stdc++.h>
#define R return
#define rep(i,a,b)for(_ i=a;i<=b;i++)
using namespace std;typedef int _;const _ N=100010;typedef unsigned long long ull;_ gc(){R getchar();}ull I(){ull x,c;while((c=gc())<'0'||c>'9');x=c^'0';while((c=gc())>='0'&&c<='9')x=x*10+c-'0';R x;}struct edges{_ T,P;}e[N<<1];_ h[N],E,s[N];_ A(_ u,_ v) {R e[++E].T=v,e[E].P=h[u],h[u]=E;}_ D(_ x,_ fa=0,_ t=0){for(_ i=h[x],y;i;i=e[i].P)if((y=e[i].T)^fa)t^=D(y,x);R s[x]-(s[x]<=t);}_ main(){for(_ n,x,y;scanf("%d",&n)!=EOF&&n;E=0,printf(D(1)?"Alice\n":"Marisa\n")){rep(i,1,n)s[i]=log2(I())+1,h[i]=0;rep(i,1,n-1)x=I()+1,y=I()+1,A(x,y),A(y,x);}R 0;}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/82807267