1. 程式人生 > 實用技巧 >GameGame CodeForces - 1384D (博弈+位運算)

GameGame CodeForces - 1384D (博弈+位運算)

GameGameCodeForces - 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 }