• CF1221E Game With String


    https://codeforces.com/problemset/problem/1221/E

    给定由 X. 组成的字符串,先手每次可以选择长度为 \(a\) 的全 . 子串变成 X,后手每次可以选择长度为 \(b\) 的全 . 子串变成 X
    问谁必胜
    \(n\le 3\times 10^5\),保证 \(a>b\)

    把每个极长的全 . 子串拿出来分别考虑
    若存在某子串长度在 \([b,a)\) 中,则后手必胜,考虑去除掉这个子串,若某时刻先手选完以后后手不能选了,后手就选这个长度 \([b,a)\) 的,此时轮到先手一定不能再选

    现在讨论不存在长度 \([b,a)\) 的子串,那么后手一定想要通过操作得到这样的子串
    若存在某子串长度在 \([2b,\infty)\) 中,那么后手可以通过一部操作得出一个长度在 \([b,a)\) 中的子串(或者说直接操作出一个长度为 \(b\) 的就行)

    • 若这种子串多余一个,那么后手必胜
    • 若这种子串只有一个,那么先手可以尝试挽救一下
      • 不好直接讨论,于是枚举先手把这个串通过一次操作分割成了 \(p,q\),若存在 \([b,a)\)\([2b,\infty)\) 长度的,必然不行,否则只剩下 \(1\)\(2\) 个长度在 \([a,2b)\) 中的
      • 那么再加上原来的长度在 \([a,2b)\) 中的子串,设共 \(x\) 个,这些串只能被先后获后手操作仅一次,则先手必胜当且仅当 \(x\) 奇数
    • 若不存在这种子串,那么若长度在 \([a,2b)\) 中的子串有偶数个,则后手胜,否则先手胜
    #define N 300006
    char s[N];
    int main(){int $=read();while($--){
    	int a=read(),b=read();read(s+1);
    	int n=std::strlen(s+1);
    	int _b=0,_ab=0,_a=0,_alen=0;
    	for(int i=1;i<=n;i++)if(s[i]=='.'){
    		int j=i;while(s[j]=='.') j++;
    		int len=j-i;
    		if(len<b);
    		else if(len<a) _b=1;
    		else if(len<b<<1) _ab++;
    		else _a++,_alen=len;
    		i=j;
    	}
    	if(_b||_a>1) write("nO\n");
    	else if(!_a) write((_ab&1)?"yEs\n":"nO\n");
    	else{
    		for(int p=0,q;_alen-p-a>=0;p++){
    			q=_alen-p-a;
    			if((p>=b<<1)||(q>=b<<1)) continue;
    			if((p>=b&&p<a)||(q>=b&&q<a)) continue;
    			if(!((_ab+(p>=b)+(q>=b))&1)) goto YES;
    		}
    		write("nO\n");continue;
    		YES:write("yEs\n");
    	}
    }
    	return SUC_RETURN;
    }
    
  • 相关阅读:
    Ubuntu 安装.net core 设置源仓储地址
    ASP.NET Core开发-MVC 使用dotnet 命令创建Controller和View
    ubuntu安装postman
    redis相关操作
    C# StringValues 类型
    MySQL时间戳与日期格式的相互转换
    C# 生成时间戳以及时间戳转换为时间
    关于vscode 使用nuget插件相关说明
    ubuntu一些命令
    使用HBuilderX新建Uniapp项目并在不同平台上运行调试
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/15543458.html
Copyright © 2020-2023  润新知