[HNOI2007]分裂游戏

题目

这个题太妙啦

我们发现如果把一堆石子看成一个独立游戏的话显然是不可以的,因为这样的话游戏根本就不独立,于是就自闭了

我们发觉这个东西本质上还是一个\(multi\)博弈,只不过这里的单个游戏变成了每一个石子,石子在不停的分裂

我们设\(sg_x\)表示一个石子在第\(x\)堆的\(SG\)函数

如果\(x=n\),那么这个石子显然不能再移动了,于是\(sg_x=0\)

如果\(x!=n\),我们就考虑这个石子分裂产生的新位置,于是\(sg_x=mex_{i<j<=k}\{sg_{j}\bigoplus sg_k\}\)

于是我们现在在\(O(n^3)\)的时间内就可以求出\(sg\)函数的值了

之后我们再\(O(n^3)\)枚举出示状态就可以了

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read() {
    char c=getchar();int x=0;while(c<'0'||x>'9') c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
int sg[55],n,T,tax[100005],m;
int main() {
    T=read();m=1;
    while(T--) {
        n=read();sg[n]=0;memset(sg,0,sizeof(sg));
        for(re int i=n-1;i;--i,++m) {
            for(re int j=i+1;j<=n;j++)
                for(re int k=j;k<=n;k++) 
                    tax[sg[j]^sg[k]]=m;
            while(tax[sg[i]]==m) sg[i]++;
        }
        int ans=0,tot=0;
        for(re int x,i=1;i<=n;i++)
            x=read()&1,ans^=(x*sg[i]);
        if(!ans) {puts("-1 -1 -1");puts("0");continue;}
        for(re int i=1;i<=n;i++)
            for(re int j=i+1;j<=n;j++)
                for(re int k=j;k<=n;k++) {
                    ans^=sg[i];ans^=sg[j];ans^=sg[k];
                    if(!ans) {
                        if(!tot) printf("%d %d %d\n",i-1,j-1,k-1);
                        tot++;
                    }
                    ans^=sg[i];ans^=sg[j];ans^=sg[k];
                }
        printf("%d\n",tot);
    }
    return 0;
}

转载于:https://www.cnblogs.com/asuldb/p/10756509.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值