Los solution to a problem Valley P3185 [[HNOI2007] split Games

First of all can be found when all the chocolate in the last bottle, you can not operate, and this time the state is doomed to failure.

Note that for each bottle of chocolate, is in the mold \ (2 \) go on to consider the significance, because FLAC can mimic upper hand operation, so will the number of chocolate beans converted to \ (0 \) or \ (1 \) .

Then consider splitting process, the location is \ (i \) of chocolate beans to split the position \ (i \) two positions in the future, and would eventually reach \ (n \) in this position, can look back transfer as \ (Nim \) game of fetch operations stones.

Then divide can be seen as \ (Nim \) pile of stones in the game is divided into smaller piles of stones, then by this property, we can \ (O (n ^ 3) \) to obtain \ (SG \ ) worth it.

Evaluating the number and the lexicographically minimal direct violence program can enumerate, when after the first operation, leaving the flip is doomed to failure state, then the legitimate operation.

Concrete realization to see the code.

\(code:\)

#include<bits/stdc++.h>
#define maxn 100
using namespace std;
template<typename T> inline void read(T &x)
{
    x=0;char c=getchar();bool flag=false;
    while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    if(flag)x=-x;
}
int T,n,ans,tot,flag;
int p[maxn],sg[maxn];
bool vis[maxn];
void SG()
{
    for(int i=n-1;i;--i)
    {
        memset(vis,false,sizeof(vis));
        for(int j=i+1;j<=n;++j)
            for(int k=j;k<=n;++k)
                vis[sg[j]^sg[k]]=true;
        int t=0;
        while(1)
        {
            if(!vis[t])
            {
                sg[i]=t;
                break;
            }
            t++;
        }
    }
}
int main()
{
    read(T);
    while(T--)
    {
        read(n),sg[n]=ans=tot=flag=0;
        for(int i=1;i<=n;++i) read(p[i]);
        SG();
        for(int i=1;i<=n;++i)
            if(p[i]%2)
                ans^=sg[i];
        for(int i=1;i<=n;++i)
        {
            if(!p[i]) continue;
            for(int j=i+1;j<=n;++j)
            {
                for(int k=j;k<=n;++k)
                {
                    if((ans^sg[i]^sg[j]^sg[k])==0)
                    {
                        tot++;
                        if(!flag)
                        {
                            flag=true;
                            printf("%d %d %d\n",i-1,j-1,k-1);
                        }
                    }
                }
            }
        }
        if(!flag) puts("-1 -1 -1");
        printf("%d\n",tot);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/lhm-/p/12508123.html