标签:ace 情况 namespace int ext space clu 不为 第一步
\(\text{Solution:}\)
回顾一下\(Nim\)游戏那个优美结论的\(\text{conclusion:}\)
将所有石子数量异或起来,若和为\(0\)则必败,否则必胜。(先手)
那分以下情况考虑:
首先是全\(0:\)此时必败,显然异或和为\(0\).
然后是异或和不为\(0\)的状态:那我们必定可以找到一个\(a_i\),将它改变,使得异或和为\(0\).
因为二进制异或下的某一位是\(1\)的话则一定有奇数个数在此处是\(1\).那么我们随意找一个,令异或和为\(k\).将\(a_i\to a_i\text{^} k\)则这个数必然比原来的\(a_i\)小。因为最高位改变了。
第三种情况是异或和为\(0\)时不存在一种移动使得下一步的异或和依旧是\(0\).
因为如果让\(a_i\to a_i*\)成立的话,则必然有\(a_i*=a_i\),是一个不合条件的移动。
那么对于这个题:第一步用\(Nim\)和判断是不是必败,第二步枚举每一个队看看能不能修改即可。
#include<bits/stdc++.h>
using namespace std;
int n,a[5000010],s;
pair<int,int>p;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%d",a+i);
for(int i=1;i<=n;++i)s^=a[i];
if(s==0){
puts("lose");
return 0;
}
for(int i=1;i<=n;++i){
int S=s;
S^=a[i];
if(a[i]>=S){
p.first=a[i]-S;
p.second=i;
a[i]-=p.first;
break;
}
}
printf("%d %d\n",p.first,p.second);
for(int i=1;i<=n;++i)printf("%d ",a[i]);
puts("");
return 0;
}
标签:ace 情况 namespace int ext space clu 不为 第一步
原文地址:https://www.cnblogs.com/h-lka/p/13059023.html