好題!個人結論很接近正解了。。。ios
把一個數化成二進制,每次至少要拿走一位,最多全拿走,不能不拿。那麼這就是一個經典的Nim問題了,子樹異或起來就是根節點的答案,隨便遞推一下就好了。spa
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\n"); 45 else printf("Marisa\n"); 46 } 47 return 0; 48 }
ps:NOIp2018模擬賽三十九不想寫,不寫了code