GameGame CodeForces - 1384D (博弈+位运算)
GameGame CodeForces - 1384D
题意:
第一行包含t(1≤t≤1e4)——测试用例的数量。
每个测试用例:
第一行包含整数n(1≤n≤1e5)表示a的长度。
第二行包含n个整数 a1,a2,…,an(0≤ai≤1e9)
a表示可以选择的元素序列。
题目要求两人博弈,初始时两个人的积分都为零,轮流选择元素序列中的数字 并将自己的积分与选取的数字进行异或操作,得到新的积分。
在取完序列中的所有数字后比较两人的积分,积分高者为胜,相同则平手。 要求判断先者的输赢情况。
思路:
由于改变积分的方法是与序列中的数字进行异或,要取得最大值就可以直接考虑最高位非0的个数。
1.当最高位非0个数为偶数时,双方各取一半无影响,继续向下遍历。
2.当最高位非0个数为奇数时:
假设最高位非0个数为 cnt
(1)若 (cnt+1)/2 是奇数:那么先手必赢
(2) 若 (cnt+1)/2 是偶数:此时当双方各取偶数个时最后一个非0项的先手权反而在后手方,所以此时考虑剩下的0项的个数,若0项的个数为奇数则先手可以先选择 0 项,先手赢,否则先手必输。
代码:
1 #include <set> 2 #include <map> 3 #include <list> 4 #include <stack> 5 #include <queue> 6 #include <deque> 7 #include <cmath> 8 #include <string> 9 #include <vector> 10 #include <cstdio> 11 #include <cstring> 12 #include <cstdlib> 13 #include <sstream> 14 #include <iostream> 15 #include <algorithm> 16 //#include <unordered_map> 17 #define INF 0x3f3f3f3f 18 #define ll long long 19 #define ull unsigned long long 20 #define FILL(a,n,v) fill(a,a+n,v) 21 #define Mset(a,v) memset(a,v,sizeof a) 22 #define Mcpy(a,b) memcpy(a,b,sizeof b) //a=b 23 #define fcio ios::sync_with_stdio(false); cin.tie(0); cout.tie(0) 24 using namespace std; 25 26 const int maxn=1e5+10; 27 int a[maxn]; 28 int t; 29 int n; 30 31 32 int main() 33 { 34 cin>>t; 35 while(t--) 36 { 37 cin>>n; 38 for(int i=1;i<=n;i++) cin>>a[i]; 39 40 int flag=0; 41 for(int i=30;i>=0;i--) //a的最大值为1e9 所以从第30位开始 42 { 43 int cnt=0; 44 for(int j=1;j<=n;j++) if((a[j]&(1<<i))!=0) cnt++; // &运算判断a[j]的第i位是否为0 45 46 if(cnt%2==1) 47 { 48 if((cnt+1)/2%2==1) flag=1; 49 else 50 { 51 if(n%2==1) flag=-1; 52 else flag=1; 53 } 54 break; 55 } 56 } 57 58 if(flag==1) cout<<"WIN"<<endl; 59 else if(flag==0) cout<<"DRAW"<<endl; 60 else cout<<"LOSE"<<endl; 61 62 } 63 return 0; 64 }