E. Tokitsukaze and Duel 【Codeforces Round #573 (Div. 2) E】【博弈】

题目链接

题目大意

有一个长度为n的01串,两个人轮流操作,每次可以选择长度为k的连续子串把他们变成相同的数字,都为1或者都为0,当这个串中所有的字符都是一样的时候结束游戏,两个人都用最优的策略,判断游戏结果

解题思路

这个博弈推的我脑仁疼。。。。。
首先我们知道,先手第一步如果不能赢的话,那他就赢不了了,后手第一步赢不了,那他了赢不了了,因为会进入无休止的扯皮的状态。

那么先手的输赢就很好判断,我们找出0的第一个位置a1和最后一个位置a2,1的第一个位置b1和最后一个位置b2,那么如果(a2-a1)<=k||(b2-b1)<=k或者整个串开始的时候都是一样的,那么先手必胜。

再来讲,如果k*2<n的话,那就一定平手,因为两步无法覆盖整个串,那么就会有无休止的扯皮,无用的反转直到平手为止

那么现在需要判断后手一步能不能赢:后手能赢的必要条件是先手不管怎么搞,后手都能赢。因为 k*2>=n 所以先手一定不会从两端取连续的序列,因为:
比如先手从左边取了连着k个把他们翻成一样的,那么剩下的长度一定是小于等于k的,后手可以一下子把剩下的给反转成一样的。
所以先手一定是从中间选一段使得中间一段是一样的。
例如这个区间是这样的:
在这里插入图片描述那么后手想要一步就要把他们反转成一样的,就要让余下的串和两端是一样的,也就是假如,两端是0和1
在这里插入图片描述
那就是要蓝色的区间都和第一元素一样,假设是0,橙色区间的都和最后一个元素一样都是1,这样,不管k这个区间先手把它转为1还是0,都可以和蓝色或者橙色的区间连接上,剩下的区间后手一步就可以翻转成和先手翻转的一样了。
所以我们枚举这个k区间,不管这个区间从哪里开始,都蓝色区间和橙色区间都是分别和首尾元素一样的话,后手就必胜。
剩下的就是平局态了
这个题完结。。。我脑瓜仁疼。。。。。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int N=1e5+5;
char s[N];
int main()
{
    int n,k;
    scanf("%d %d",&n,&k);
    scanf("%s",s+1);
    int a1=0,a2=0,b1=0,b2=0;
    for(int i=1;i<=n;i++)
    {
        if(s[i]=='0'&&a1==0)
            a1=i;
        if(s[i]=='1'&&b1==0)
            b1=i;
    }
    for(int i=n;i>=1;i--)
    {
        if(s[i]=='0'&&a2==0)
            a2=i;
        if(s[i]=='1'&&b2==0)
            b2=i;
    }
    if((a2-a1+1)<=k||(b2-b1+1)<=k||(b1==0&&b2==0)||(a1==0&&a2==0))//先手必胜状态
    {
        printf("tokitsukaze\n");
        return 0;
    }
    if(k*2<n)
    {
        printf("once again\n");
        return 0;
    }
    int flag=0;
    for(int i=2;i+k<n;i++)//枚举k区间
    {
        if(s[i]!=s[1])
            flag=1;
        if(s[n-i+1]!=s[n])
            flag=1;
    }
    if(!flag)
        printf("quailty\n");
    else
        printf("once again\n");
    return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值