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

hdu 4388 Stone Game II 博弈

題目連結:hdu 4388

參考部落格:https://blog.csdn.net/y1196645376/article/details/52143551

題意:

最初有n堆石子,每堆石子個數已知。兩人輪流執行操作,如果當某人無法執行有效操作時即輸。

操作分兩步:

    第一步為:選擇其中一堆石子假定石子個數為a,拿走個數不為0的一些石子使得該堆石子剩餘k個並且保證(0 < k < a,k^a < a),^為異或符號。

    第二步為:加入一堆新的石子,石子個數為k^a,當然你也可以使用技能使得加入的石子個數變為(2k)^a

。不過每個人每局遊戲只能使用一次技能。

無法執行有效操作即第一步或者第二步無法執行時。

 

題解:直接看程式碼,裡面有很詳細的註釋。

///先看下題目要求,每次留下的k,滿足 0<k<n && kXORn <n,
///這說明,k只能在n中取二進位制位1的數位,例如n=5(101),那麼k只能是4(100)或者1(001)
///還能知道堆數為2^i時(二進位制只有一位1),不能再分了,已到達邊界了。
///然後我們假設先考慮一堆石子(n=1),k為這堆石子二進位制位為1的個數,假設為偶數,先手win,也就是n+k為奇數時,先手win
///接著我們考慮有多堆石子(n>1),sum為這堆石子二進位制1的個數,類比於一堆石子,sum+n為奇數時先手win,多堆可以看做單堆單堆的取,
///對了,每位選手還有一次技能加成的機會,我們要清楚的一點的是,這次加成的是用在新加堆上的,並且也不會改變新加堆的二進位制位為1的個數
///例如n=13(1101),留k=5(101),2*k=1010, k XOR n=1000 ,2*k XOR n=0111,可見,不管用不用技能,新加堆的二進位制位為1的個數的奇偶數還是沒變。over。

/*
例如
n=15(1111)

1 111 先手
1 100 11 後手
1 100 1 1 先手

*/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>


using namespace std;

int main()
{

    int ncase;
    scanf("%d",&ncase);

    for(int T=1;T<=ncase;T++)
    {
        int n;
        scanf("%d",&n);

        int x,sum=0;

        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            sum+=__builtin_popcount(x); ///庫函式查詢x數字二進位制為1的個數,
            ///這庫函式有個小坑,前面的下橫線要兩條,艹。
        }

        if((sum+n)&1) printf("Case %d: Yes\n",T);
        else printf("Case %d: No\n",T);
    }
    return 0;
}