Treblecross

9 篇文章 0 订阅

传送门

题解:题目要求3个X不能相邻,会产生相邻的位置就成了禁区,则X会将其分成很多段,每一段只包含可以下的位置就是其后继状态,预处理出.数目的sg函数,最后将分段后的sg异或就是答案,合法位置就是选了当前位置后局势转变为先手必败

AC代码:

#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#define ll long long
using namespace std;
const int maxn=10000;
char mp[205];
int fa[205],sg[205];
int y[205],s[205],s1[205];
int ans[205];
int getsg(int x){
    memset(fa,-1,sizeof(fa));
    for(int a=1;a<=x;a++){
        int l=max(a-3,0);
        int r=max(x-a-2,0);
        fa[sg[l]^sg[r]]=1;
    }
    int ans1=0;
    for(;;ans1++){
        if(fa[ans1]!=1)
            return ans1;
    }
}
void init(){
    sg[0]=0;
    sg[1]=sg[2]=sg[3]=1;
    for(int a=4;a<=200;a++)
        sg[a]=getsg(a);
}
int get(int len,int t){
    int z=0;
    for(int a=0;a<len;a++){
        if(mp[a]=='X'){
            y[a]=t;
            if(a+1<len)
                y[a+1]=t;
            if(a+2<len)
                y[a+2]=t;
            if(a-1>=0)
                y[a-1]=t;
            if(a-2>=0)
                y[a-2]=t;
        }
        else{
            if((a+1<=len&&a-1>=0&&mp[a+1]=='X'&&mp[a-1]=='X')||(a+1<=len&&a+2<=len&&mp[a+1]=='X'&&mp[a+2]=='X')||(a-1>=0&&a-2>=0&&mp[a-1]=='X'&&mp[a-2]=='X'))
                 ans[++z]=a+1;
        }
    }
    return z;
}
void get1(int len,int t){
    int num=0;
    for(int a=len-1;a>=0;a--){
        if(y[a]==t)
        s[a]=s[a+1],num=0;
        else{
            num++;
            s[a]=s[a+num]^sg[num];
        }
    }
    s1[0]=0;
    num=0;
    for(int a=0;a<len;a++){
        if(y[a]==t)
            s1[a+1]=s1[a],num=0;
        else{
            num++;
            s1[a+1]=s1[a-num+1]^sg[num];
        }
    }
}
int main( )
{
    init();
    s[0]=0;
    int t,len;
    scanf("%d",&t);
    for(int t1=1;t1<=t;t1++){
        scanf("%s",mp);
        len=strlen(mp);
        s[len]=0;
        printf("Case %d:",t1);
        int ju=get(len,t1);
        if(ju!=0){
            for(int a=1;a<=ju;a++)
                printf(" %d",ans[a]);
            printf("\n");
            continue;
        }
        get1(len,t1);
        for(int a=1;a<=len;a++){
            int b=a-1;
            if(y[b]==t1)
                continue;
            int sg1=0;
            if(b-3>=0)
                sg1^=s1[b-2];
            if(b+2<len)
                sg1^=s[b+3];
            if(sg1==0){
                printf(" %d",a);
                //printf("\n%d %d %d %d\n",b-2,b+3,s1[b-2],s[b+3]);
                ju=1;
            }
        }
        if(!ju)
            printf(" %d",ju);
        printf("\n");
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值