简单题*10000
Description
?已知一排硬幣中有n個硬幣正面朝上,輸入正面朝上的硬幣的位置ai(可能重復)。兩人輪流操作,每次操作可以翻轉1,2,或則3枚硬幣(不一定連續),其中翻轉的最右的硬幣必須是正面朝上的,最后不能翻轉的為負
?
Input
?第一行輸入一個組數t(t ≤?100)。
對于每組數據第一行有一個正整數N(0?≤ N ≤?5000)。
第二行N個非負整數c1,c2,...,cN(0 ≤ ai ≤ 1e9)。
Output
如果先手必勝輸出Yes,否則輸出No。
?
Sample Input
2 1 0 4 0 1 2 3Sample Output
Yes NoHINT
題解
定義硬幣全反時的sg為0,現在單個游戲就是只有一枚硬幣朝上,其余都是反,其他情況都可以由單一游戲組合而成。如果位置i有一個正面朝上的硬幣,其余都是反,那么這枚硬幣翻過來的時候,它可以到達的局面是1、sg = 0 ? 2、sg(j)j位置的硬幣朝上,其余都是反(j<i) 3、出現兩個正面朝上的硬幣,變成組合游戲sg(j)和sg(k)。我們把sg函數打表出來就可以找到規律。(hdu3537)
初始編號從0開始。
當N==1時,硬幣為:正,先手必勝,所以sg[0]=1.
當N==2時,硬幣為:反正,先手必贏,先手操作后可能為:反反或正反,方案數為2,所以sg[1]=2。
當N==3時,硬幣為:反反正,先手必贏,先手操作后可能為:反反反、反正反、正反正、正正反,方案數為4,所以sg[2]=4。
位置x:0??1??2??3??4???5????6???7????8?????9??10??11??12??13??14...
sg[x]:??1??2??4??7??8??11 13 14??16??19??21??22??25??26??28…
看上去sg值為2x或者2x+1。我們稱一個非負整數為odious,當且僅當該數的二進制形式的1出現的次數是奇數,否則稱作evil。所以1,2,4,7是odious因為它們的二進制形式是1,10,100,111.而0,3,5,6是evil,因為它們的二進制形式是0,11,101,110。而上面那個表中,貌似sg值都是odious數。所以當2x為odious時,sg值是2x,當2x是evil時,sg值是2x+1.
這樣怎么證明呢?我們會發現發現,
?????????????????????????????????????????????????????evil^evil=odious^odious=evil
?????????????????????????????????????????????????????evil^odious=odious^evil=odious
假設剛才的假說是成立的,我們想證明下一個sg值為下一個odious數。注意到我們總能夠在第x位置翻轉硬幣到達sg為0的情況;通過翻轉第x位置的硬幣和兩個其它硬幣,我們可以移動到所有較小的evil數,因為每個非零的evil數都可以由兩個odious數異或得到;但是我們不能移動到下一個odious數,因為任何兩個odious數的異或都是evil數。
?
假設在一個Mock?Turtles游戲中的首正硬幣位置x1,x2,…,xn是個P局面,即sg[x1]^…^sg[xn]=0.那么無可置疑的是n必定是偶數,因為奇數個odious數的異或是odious數,不可能等于0。而由上面可知sg[x]是2x或者2x+1,sg[x]又是偶數個,那么x1^x2^…^xn=0。相反,如果x1^x2^…^xn=0且n是偶數,那么sg[x1]^…^sg[xn]=0。這個如果不太理解的話,我們可以先這么看下。2x在二進制當中相當于把x全部左移一位,然后補零,比如說2的二進制是10,那么4的二進制就是100。而2x+1在二進制當中相當于把x全部左移一位,然后補1,比如說2的二進制是10,5的二進制是101。現在看下sg[x1]^…^sg[xn]=0,因為sg[x]是2x或者2x+1,所以式子中的2x+1必須是偶數個(因為2x的最后一位都是0,2x+1的最后一位都是1,要最后異或為0,2x+1必須出現偶數次)
#include <cstdio> #include <cstdlib> #include <cstring> #include <bitset> #include <cmath> #include <cctype> #include <iostream> #include <algorithm> #include <string> #include <vector> #include <queue> #include <map> #include <set> #include <sstream> #include <iomanip> using namespace std; typedef long long ll; typedef unsigned long long ull; const ll inff = 0x3f3f3f3f3f3f3f3f; #define FOR(i,a,b) for(int i(a);i<=(b);++i) #define FOL(i,a,b) for(int i(a);i>=(b);--i) #define REW(a,b) memset(a,b,sizeof(a)) #define inf int(0x3f3f3f3f) #define si(a) scanf("%d",&a) #define sl(a) scanf("%lld",&a) #define sd(a) scanf("%lf",&a) #define ss(a) scanf("%s",a) #define mod ll(6666666) #define pb push_back #define eps 1e-6 #define lc d<<1 #define rc d<<1|1 #define Pll pair<ll,ll> #define P pair<int,int> #define pi acos(-1) int n,a[100008]; int as(int x) {int k=0;while (x){if (x&1) k++;x>>=1;}return !(k&1); } int main() {cin.tie(0);cout.tie(0);//freopen("game001.in","r",stdin);//freopen("game001.out","w",stdout);int tt;cin>>tt;while(tt--){si(n);FOR(i,1,n) si(a[i]);sort(a+1,a+n+1);int k=unique(a+1,a+n+1)-a-1,s=0;FOR(i,1,k){a[i]*=2ll;if(as(a[i])) a[i]++;s^=a[i];}if(s) puts("Yes");else puts("No");}return 0; }?
總結