首页 > 其他 > 详细

[HNOI2007]分裂游戏

时间:2019-04-23 15:17:17      阅读:147      评论:0      收藏:0      [点我收藏+]

题目

这个题太妙啦

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

我们发觉这个东西本质上还是一个\(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;
}

[HNOI2007]分裂游戏

原文:https://www.cnblogs.com/asuldb/p/10756509.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!