(2016北京集训十三)【xsy1531】魔法游戏 - Nim游戏

题解:

好题!我的结论很接近正解了。。。

把一个数化成二进制,每次至少要拿走一位,最多全拿走,不能不拿。那么这就是一个经典的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\n");
45         else printf("Marisa\n");
46     }
47     return 0;
48 }

 ps:NOIp2018模拟赛三十九不想写,不写了

posted @ 2018-09-24 18:19  DCDCBigBig  阅读(141)  评论(0编辑  收藏  举报