Xor 思維題
Xor 思維題
題目描述
小\(Q\)與小\(T\)正在玩一棵樹。這棵樹有\(n\)個節點,編號為 \(1\),\(2\) \(3...n\),由\(n-1\)條邊連線,每個節點有一個權值\(w_i\)。
在這個遊戲中,小 \(Q\) 需要選擇一些節點。他可以選擇任意個數的點(小\(Q\)一定會選擇最優策略),但是一條邊連線的兩個節點不能同時被選。
當小\(Q\)選完後,小\(T\)將選擇剩下的節點。這樣這棵樹上的每個點都將被小\(Q\)或者小\(T\)選擇。
最後兩人的分數分別為自己選擇的點的權值異或和,分數大的一方獲勝,當然有可能是平局。
輸入格式
第一行一個整數\(T(T \leq 20)\)
接下來\(T\)組,對於每一組,第一行一個整數\(n\)
第二行有\(n\)個整數,為\(w_1,w_2...w_n\),
接下來\(n-1\)行,每行兩個整數\(x\),\(y\),表示\(x\)和\(y\)
之間有一條邊連線
輸出格式
對於每一組,答案只有一行,如果小\(Q\)獲勝輸出\(Q\),小\(T\)獲勝輸出\(T\),如果平局輸出\(D\)。
樣例
樣例輸入
2
3
2 2 2
1 2
1 3
4
7 1 4 2
1 2
1 3
2 4
樣例輸出
Q
D
樣例解釋
在第一組中,小\(Q\)選擇任意一個節點,分數為\(2\),小\(T\)選擇剩下兩個節點,分數為\(0\)
在第二組中,小\(Q\)最好只能和小\(T\)平局,所以輸出\(D\)
資料範圍與提示
對於$30% \(的資料,\)n \leq 20$
對於\(100\%\)的資料,\(n \leq 100000\),\(w_i \leq 10^9\)。
分析
一道不錯的思維題
首先我們考慮平局的情況
如果整棵樹上所有節點的異或和恰好為\(0\)的話
那麼無論先手選走哪一些點,後手選走的點一定與先手選走的點相同,這樣才能保證異或和為\(0\)
如果整棵樹上所有節點的異或和不為\(0\),那麼我們在二進位制位中會找到一個最高位的\(1\)
先手只要把這個\(1\)選走,那麼必定可以獲勝
程式碼
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+5; int a[maxn],n; int main(){ int t; scanf("%d",&t); while(t--){ int tot=0; memset(a,0,sizeof(a)); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); tot^=a[i]; } for(int i=1;i<n;i++){ int aa,bb; scanf("%d%d",&aa,&bb); } if(tot==0) printf("D\n"); else printf("Q\n"); } return 0; }