[BOZJ 1188][HNOI2007]分裂遊戲(博弈論)

Description


聰聰和睿睿最近迷上了一款叫做分裂的遊戲。 該遊戲的規則試: 共有 n 個瓶子, 標號爲 0,1,2…..n-1, 第 i 個瓶子中裝有 p[i]顆巧克力豆,兩個人輪流取豆子,每一輪每人選擇 3 個瓶子。標號爲 i,j,k, 並要保證 i < j , j < = k 且第 i 個瓶子中至少要有 1 顆巧克力豆,隨後這個人從第 i 個瓶子中拿走一顆豆 子並在 j,k 中各放入一粒豆子(j 可能等於 k) 。如果輪到某人而他無法按規則取豆子,那麼他將輸 掉比賽。勝利者可以拿走所有的巧克力豆! 兩人最後決定由聰聰先取豆子,爲了能夠得到最終的巧克力豆,聰聰自然希望贏得比賽。他思考 了一下,發現在有的情況下,先拿的人一定有辦法取勝,但是他不知道對於其他情況是否有必勝 策略,更不知道第一步該如何取。他決定偷偷請教聰明的你,希望你能告訴他,在給定每個瓶子 中的最初豆子數後是否能讓自己得到所有巧克力豆,他還希望你告訴他第一步該如何取,並且爲 了必勝,第一步有多少種取法? 假定 1 < n < = 21,p[i] < = 10000

Input


輸入文件第一行是一個整數t表示測試數據的組數,接下來爲t組測試數據(t<=10)。每組測試數據的第一行是瓶子的個數n,接下來的一行有n個由空格隔開的非負整數,表示每個瓶子中的豆子數。

Output


對於每組測試數據,輸出包括兩行,第一行爲用一個空格兩兩隔開的三個整數,表示要想贏得遊戲,第一步應該選取的3個瓶子的編號i,j,k,如果有多組符合要求的解,那麼輸出字典序最小的一組。如果無論如何都無法贏得遊戲,那麼輸出用一個空格兩兩隔開的三個-1。第二行表示要想確保贏得比賽,第一步有多少種不同的取法。

Sample Input


2
4
1 0 1 5000
3
0 0 1

Sample Output


0 2 3
1
-1 -1 -1
0

Solution


RE一次(因爲數組開在了主函數裏面 剛知道這樣也會RE Orz)
WA一次(因爲in[ ]數組開小了)

因爲可以預處理,所以把0到n-1反過來,變成從序號大的地方往序號小的方向移動
首先明確每個巧克力之間豆相互獨立
而在i處拿走一個,可以在j,k處各加一個,所以此處後繼狀態的sg函數可以用sg[j]^sg[k]表示
然後枚舉√

#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<cstdlib>
using namespace std;
int t,n,sg[25];
bool in[50];
int main()
{
    sg[0]=0;
    for(int i=1;i<=21;i++)
    {
        memset(in,0,sizeof(in));
        for(int j=i-1;j>=0;j--)
            for(int k=j;k>=0;k--)
            {
                in[sg[j]^sg[k]]=1;
            }
        int l=0;
        while(in[l])l++;
        sg[i]=l;
    }
    scanf("%d",&t);
    while(t--)
    {
        int ans=0,p;
        scanf("%d",&n);
        for(int i=n-1;i>=0;i--)
        {
            scanf("%d",&p);
            if(p&1)
            ans^=sg[i];
        }
        int cnt=0;
        if(!ans)printf("-1 -1 -1\n");
        else 
        {

            for(int i=n-1;i>=0;i--)
            {
                for(int j=i-1;j>=0;j--)
                    for(int k=j;k>=0;k--)
                    {
                        if(!(ans^sg[i]^sg[j]^sg[k]))
                        {
                            if(!cnt)
                            printf("%d %d %d\n",n-1-i,n-1-j,n-1-k);
                            cnt++;
                        }
                    }
            }
        }
        printf("%d\n",cnt);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章