代码来自于蓝桥杯2021年第十二届省赛真题-异或数列_贾斯特比雷的博客-CSDN博客_蓝桥杯异或数列
思想讲的很清楚。从最高位开始看,只有一个1必然先手胜,偶数个1必然在本位打平,因为优势会互相抵消掉(也可能互相给对方异或成0了,总之打平),奇数个1就要看本位0有多少个,a b互相抢最后的翻转权,如果是偶数个0则先手胜,否则后手胜
憨憨因为看不懂而自己加了一些注释
//2021省赛G-异或数列 #include#include //#define rep(i,a,b) for(int i=(a);i<=(b);i++) //#define _for(i,a,b) for(int i=(a);i<(b);i++) using namespace std; const int N = 200000+10; int T,n,ans,a,b,sum; int x[N],num[20+5]; void count() //存储各位上1的个数 { sum=0; memset(num,0,sizeof(num)); // rep(i,1,n) for(int i=1;i<=n;i++) { int xi=x[i]; sum^=xi; int pos=0; while(xi){ if(xi&1) num[pos]++; //从低位开始,按位与 //比如xi为5,二进制101,5&1相当于 101&1,从低位开始与 pos++; //无论这一位是不是1 pos都++,也就是在相应为1的位上num才++ xi>>=1; //右移一位再赋给xi,低位抛弃,高位补0 //右移相当于除以2,如5的二进制为101,右移之后为010,变成了2 } } } void solve(){ count(); //计算各个位上的1有多少个 if(!sum){ cout<<0< =0;i--){ //从高位开始看 int num0=n-num[i]; //本次n个数,num存储每位有几个1 num0为这一位有几个0 if(num[i]%2==0){ //这一位有偶数个1,这一位上a b必然打平 continue; } else if(num[i]==1){ //这一位只有一个1 先手胜 cout<<1< T; while(T--){ cin>>n; //本次有n个数 //rep(i,1,n) for(int i=1;i<=n;i++) { cin>>x[i]; } solve(); } return 0; }
一点小tips,原博最后说的两个函数,查了一下,原因在l关于ios::sync_with_stdio(false);和 cin.tie(0)加速c++输入输出流_青梦丶的博客-CSDN博客_ios::sync_with_stdio(false);jjj
简单来说, 就是输入输出方面,使用cin cout要比scanf printf慢,这句话是用来略微加快速度的,但其实用完依旧慢,而且加完之后两种混用会出问题。
以下来自原博:
sync_with_stdio
这个函数是一个“是否兼容stdio”的开关,C++为了兼容C,保证程序在使用了std::printf和std::cout的时候不发生混乱,将输出流绑到了一起。
cin,cout之所以效率低,是因为先把要输出的东西存入缓冲区,再输出,导致效率降低,而这段语句可以来打消iostream的输入 输出缓存,可以节省许多时间,使效率与scanf与printf相差无几.
关于tie的解释来自关于ios::sync_with_stdio(false);和cin.tie(0);cout.tie(0);_绀香零八的博客-CSDN博客
以下来自原博:
tie是将两个stream绑定的函数,空参数的话返回当前的输出流指针。
在默认的情况下cin绑定的是cout,每次执行 << 操作符的时候都要调用flush,这样会增加IO负担。可以通过tie(0)(0表示NULL)来解除cin与cout的绑定,进一步加快执行效率。



