第十五届吉林程序设计省赛The 15th Jilin Provincial Collegiate Programming Contest I. Nim Game(树状数组,线性基)
Posted quinn18
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第十五届吉林程序设计省赛The 15th Jilin Provincial Collegiate Programming Contest I. Nim Game(树状数组,线性基)相关的知识,希望对你有一定的参考价值。
文章目录
题意
:
N
i
m
Nim
Nim 游戏,轮流从几堆石头中取出石头。在每一轮,玩家必须从一堆石头中取出一颗或多颗石头。不能拿石头的人输掉比赛。
戴安娜和爱娃可以每轮可以进行两个操作
o
p
=
=
1
op==1
op==1, 在一个区间内选出几堆进行
N
i
m
Nim
Nim 游戏,艾娃先手,戴安娜选牌堆,问戴安娜是否有机会胜利;
o
p
=
=
2
op==2
op==2, 给
[
l
,
r
]
[l,r]
[l,r] 的石头堆
a
[
i
]
a[i]
a[i] 加上
x
x
x 个石头。
题解
: N i m Nim Nim 博弈的结论是 所有 a [ i ] a[i] a[i]异或起来等于 0 0 0,先手必败。
所以
o
p
1
op1
op1 就是询问
a
[
l
.
.
.
r
]
a[l...r]
a[l...r] 内能否选出若干数使得异或为
0
0
0。
然后我们知道 线性基里面的任意一些数异或起来都不能得到 0 ,
那么问题最后转化为询问
[
l
,
r
]
[l,r]
[l,r] 的序列是否为线性基,是线性基那么先手必胜,戴安娜必败,假如不是线性基,那么就能找出任意一些数异或起来等于
0
0
0使得戴安娜胜。
o p 2 op2 op2 是区间操作可以用线段树或者树状数组差分
代码
:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e6+5;
int n;
int a[N];
int c[N],b[N];
int lowbit(int x)
return x&(-x);
void add(int i, int k)
while(i<=n)
c[i]+=k;
i+=lowbit(i);
int getsum(int i)
int res=0;
while(i>0)
res+=c[i];
i-=lowbit(i);
return res;
bool insert(int x)
for(int i=30; i>=0; i--)
if(x&(1<<i))
if(b[i]) x^=b[i];
else
b[i]=x;
return 0;
return 1;
signed main()
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int q;
cin>>n>>q;
for(int i=1; i<=n; i++)
cin>>a[i];
while(q--)
int op,l,r;
cin>>op>>l>>r;
if(op==1)
int x;
cin>>x;
add(l, x);
add(r+1, -x);
else
bool fl=0;
for(int i=0; i<=30; i++) b[i]=0;
for(int i=l; i<=r; i++)
if(insert(a[i]+getsum(i)))
fl=1;
break;//因为1e9范围最长的线性基为31,所以不会t
if(fl) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
return 0;
总结
Qaq
以上是关于第十五届吉林程序设计省赛The 15th Jilin Provincial Collegiate Programming Contest I. Nim Game(树状数组,线性基)的主要内容,如果未能解决你的问题,请参考以下文章