您的位置:首页 > 其它

【题解】玲珑学院oj1087 Alice and Bob

2017-02-14 21:36 176 查看
题目链接

题意:给定一棵满二叉树,每个点有一个权值。两人轮流操作,每次操作可以选一个点u,将点u的权值减小x,0<x≤au(点u的权值),若点u不是叶子节点,则再选择u的一个儿子v,将v的权值加上x。不能操作者输。问先手有多少种必胜策略。

分析:将叶子节点所在的层定义为第1层,向上层数递增。

        记sg为奇数层节点权值的异或和。则先手必胜当且仅当sg≠0。

        证明思路:1.sg≠0的状态可经过一次操作到达sg=0的状态。

                            2.sg=0的状态经过一次操作必到达sg≠0的状态。

        从而先手的必胜策略即第一步把sg变成0的操作种数。若选取的是奇数层节点u,则当sg^au∈[0,au)时可以取x=au-sg^au。若选取的是偶数层节点u,设u的左、右儿子分别为l、r,则当sg^al∈(al,al+au]时可以取x=sg^al-al将其加到节点l的权值,对r同理。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1<<21;
int n,a[maxn];
int main()
{
int T;cin>>T;
while (T--)
{
scanf("%d",&n);
int k=0,sg=0,ans=0;
for (int i=0;i<n;i++)
for (int j=1;j<=(1<<i);j++)
{
k++;scanf("%d",&a[k]);
if ((n-1-i)%2==0) sg^=a[k];
}
k=0;
for (int i=0;i<n;i++)
for (int j=1;j<=(1<<i);j++)
{
k++;
if ((n-1-i)%2==0)
{
if ((sg^a[k])>=a[k]) continue;
if (i==n-1) ans++;
else ans+=2;
}
else
{
int sg1=sg^a[2*k],sg2=sg^a[2*k+1];
if (sg1>a[2*k]&&sg1<=a[2*k]+a[k]) ans++;
if (sg2>a[2*k+1]&&sg2<=a[2*k+1]+a[k]) ans++;
}
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息