题解:
好题!我的结论很接近正解了。。。
把一个数化成二进制,每次至少要拿走一位,最多全拿走,不能不拿。那么这就是一个经典的Nim问题了,子树异或起来就是根节点的答案,随便递推一下就行了。
代码:
1 #include<algorithm>
2 #include<iostream>
3 #include<cstring>
4 #include<cstdio>
5 #include<cmath>
6 #include<queue>
7 #define inf 2147483647
8 #define eps 1e-9
9 using namespace std;
10 typedef unsigned long long ll;
11 struct edge{
12 int v,next;
13 }a[200001];
14 int n,u,v,tot=0,num[100001],head[100001];
15 ll x;
16 void add(int u,int v){
17 a[++tot].v=v;
18 a[tot].next=head[u];
19 head[u]=tot;
20 }
21 int dfs(int u,int fa){
22 int ret=num[u],tp=0;
23 for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
24 int v=a[tmp].v;
25 if(v!=fa)tp^=dfs(v,u);
26 }
27 if(ret<=tp)ret--;
28 return ret;
29 }
30 int main(){
31 while(scanf("%d",&n)==1){
32 memset(head,-1,sizeof(head));
33 tot=0;
34 for(int i=1;i<=n;i++){
35 //scanf("%lld",&x);
36 cin>>x;
37 num[i]=(int)log2(x)+1;
38 }
39 for(int i=1;i<n;i++){
40 scanf("%d%d",&u,&v);
41 add(u+1,v+1);
42 add(v+1,u+1);
43 }
44 if(dfs(1,-1))printf("Alice
");
45 else printf("Marisa
");
46 }
47 return 0;
48 }
ps:NOIp2018模拟赛三十九不想写,不写了