zoukankan      html  css  js  c++  java
  • [JZOJ 5912] [NOIP2018模拟10.18] VanUSee 解题报告 (KMP+博弈)

    题目链接:

    https://jzoj.net/senior/#contest/show/2530/2

    题目:

      众所周知,cqf童鞋对哲学有着深入的理解和认识,并常常将哲学思想应用在实际生活中,例如锻炼摔角技术或者研究化(fa)学。
      由于cqf童鞋哲学造诣太过高深,以至于影响到了pty,他们常常给在一块VanUSee。Van的都是一些像“装备回收交易自由”、“开局一条鲲进化全靠吞”、“今晚八点是兄弟就来肝”这样高端大气上档次的著名USee。
      有一天他们决定Van一个亲民的USee来和大家分享他们的哲学心路历程
    规则是这样的:
           “给定两个串S和T,|S| >= |T|。
           cqf和pty轮流操作串S,cqf先手。
           对于每次操作,cqf或pty会选择删掉S的第一位或最后一位。
           当操作以后的串的长度等于|T|时,游戏停止。
           如果停止时的串=T,则pty获胜,否则cqf获胜。”
           cqf和pty的哲学思维都很强,他们都能采取最优的策略来行动
           作为高级玩家的苏巴先生在一旁观战,他早已看穿了这个USee的本质,当两个串给出的那一瞬间胜负已分,然而不是所有围观者的水平都像苏巴先生那么高,其中也没有五年级的积分小哥,他们又想知道结果,于是围观者们找到了能预见一局围棋接下来40手的你。

    题解:

    我们简化状态,设当前左边取了l个,右边取了r个,状态定义为r-l

    一开始状态为0,每次操作都让它+1或者-1。双方轮流操作,总共操作|S|-|T|次,显然最终状态的奇偶相同

    考虑当|S|-|T|是奇数的时候,最后一次操作是先手做,它肯定往不是目标状态走,那么一个位置i在最后一次操作前是目标状态当且仅当它和它-1都是目标状态(目标状态指的是S中i-m+1~i这一段和T完全一样)

    于是全部转化为|S|-|T|为偶数的情况

    假如 0 是目标状态,那么显然后手会赢,因为无论先手往哪里走后手都可以把他拉 回来

    如果 0 不是,并且-2 和 2 不全是,那么先手一定会朝不是的那一边走,后手无论 如何都没有办法将它拉回到是的那一边了

    因此后手会赢当且仅当 0 是目标状态或者-2 和 2 都是目标状态 否则都是先手赢

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    const int N=1e5+15;
    int t;
    int nxt[N],goal[N<<1],pos[N];
    char a[N],b[N];
    int main()
    {
        freopen("vanusee.in","r",stdin);
        freopen("vanusee.out","w",stdout);
        scanf("%d",&t);
        while (t--)
        {
            scanf("%s",a+1);
            int n=strlen(a+1);
            scanf("%s",b+1);
            int m=strlen(b+1);
            memset(nxt,0,sizeof(nxt));
            memset(goal,0,sizeof(goal));
            memset(pos,0,sizeof(pos));
            for (int i=2,j=0;i<=m;i++)
            {
                while (j&&b[j+1]!=b[i]) j=nxt[j];
                if (b[j+1]==b[i]) ++j;
                nxt[i]=j;
            }
            for (int i=1,j=0;i<=n;i++)
            {
                while (j&&(b[j+1]!=a[i]||j==m)) j=nxt[j];
                if (b[j+1]==a[i]) ++j;
                if (j==m) pos[i]=1;
            }
            if ((n-m)&1) for (int i=1;i<=n;i++) goal[n+m-2*i+1+n]=pos[i-1]&pos[i];
            else for (int i=1;i<=n;i++) goal[n+m-2*i+n]=pos[i];
            if (goal[n]||(goal[n-2]&&goal[n+2])) puts("pty");
            else puts("cqf");
        }
        return 0;
    }
  • 相关阅读:
    js中属性点.和中括号[]的关系。
    jQuery中的$(window).load()与$(document).ready()以及jquery $(document).ready() 与window.onload的区别
    今天中了一个脚本病毒。把我的所有 html 加了 vbs 脚本,WriteData 是什么鬼?
    原生js 当前时间 倒计时代码
    一看就懂得移动端rem布局、rem如何换算
    使用CSS实现三栏自适应布局(两边宽度固定,中间自适应)
    js运算符的一些特殊应用
    中文目录对 sublime text 有什么影响?
    Spring的注解@Qualifier小结
    伪共享(False Sharing)
  • 原文地址:https://www.cnblogs.com/xxzh/p/9813893.html
Copyright © 2011-2022 走看看