hdu 4388 Stone Game II
阿新 • • 發佈:2017-12-28
one put blog str ace while 不能 cas names
Stone Game II
HDU - 4388
題目大意:
給出n堆物品,每堆物品都有若幹件,現在A和B進行遊戲,每人每輪操作一次,按照如下規則:
1. 任意選擇一個堆,假設該堆有x個物品,從中選擇k個,要保證0<k<x且0<(x^k)<k。
2. 再增加一個大小為x^k的堆(也就相當於將一個x個物品的堆變成一個k個物品的堆和一個x^k個物品的堆),另外有一個技能,可以將這個大小為x^k的堆變成(2*k)^x的堆,但是這個技能每個人只有一次機會可以使用。
現在問兩人輪流操作,都采取最優策略,最後不能操作的人輸,問誰會贏。
/* 先不考慮技能,其實每輪的操作就是將一個大小為x的堆分成大小為k和(x^k)的堆,這裏很關鍵的一點是要能發現分堆之前x中二進制1的個數與分堆之後k與(x^k)的二進制1個數和的奇偶性是相同的。這個結論可以這樣想,考慮x的某一位p,分四種情況: 1. 如果x的第p位為1且k的第p位也為1,那麽(x^k)的第p位就是0. 2. 如果x的第p位為1且k的第p位也為0,那麽(x^k)的第p位就是1. 3. 如果x的第p位為0且k的第p位也為1,那麽(x^k)的第p位就是1. 4. 如果x的第p位為0且k的第p位也為0,那麽(x^k)的第p位就是0. 可以發現無論哪種情況,奇偶性都不會發生變化,這是本題的關鍵。 另外考慮遊戲怎麽終止,很顯然當一個堆x的二進制1的個數只有1個的時候,就不能再分了,那麽如果所有的堆都這樣,遊戲就終止了,關鍵看從開始到終止需要奇數步還是偶數步就能判斷輸贏。 假設這些堆最後會分成y個堆,那麽一共就分了y-n次,每個堆大小的二進制1個數都是1,這樣二進制1的總是就是y,而y和x二進制1的個數z已經證明奇偶性相同,所以y-n和z-n奇偶性就是相同的,所以我們只需要判斷z-n的奇偶性,這題就解決了,非常巧妙。*/ #include<iostream> #include<cstdio> using namespace std; int n,T; int count(int x){ int res=0; while(x){ res+=x&1; x>>=1; } return res; } int main(){ freopen("Cola.txt","r",stdin); scanf("%d",&T); for(int c=1;c<=T;c++){ printf("Case %d: ",c); scanf("%d",&n); int cnt=0,x; for(int i=1;i<=n;i++){ scanf("%d",&x); cnt+=count(x); } cnt-=n; if(cnt&1)puts("Yes"); else puts("No"); } return 0; }
hdu 4388 Stone Game II