1. 程式人生 > >hdu 4388 Stone Game II

hdu 4388 Stone Game II

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