Educational Codeforces Round 163 (Rated for Div. 2)题解

A. Special Characters(Problem - A - Codeforces

题目大意:给定一个正整数n,需要输出一个字符串s,s中需要有n个满足要求的字符,对于字符的要求:对于该字符,它的左右有且仅有一个字符与它相同。如果这样的字符串不存在的话输出NO。

思路:这题如果我们有一串相同的字符,显然只有最左边和最右边两个字符是合法字符,不管这串字符有多长,但它只有大于等于2才是有效的,所以当n为偶数的时候,我们输出n/2组两个字符相同的就可,否则就不成立。输出的时候记得每输出两个后换一种字符。

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n;
		scanf("%d",&n);
		if(n&1) printf("NO\n");
		else
		{
			printf("YES\n");
			for(int i=0;i<n/2;i++)
			{
				char c='A'+i%26;
				printf("%c%c",c,c);
			}
			printf("\n");
		}
	}
}

B. Array Fix(Problem - B - Codeforces

题目大意:给定一个n长的数组a[],这些数都是一位数或者两位数,对数组中的每个两位数,我们可以将它拆成两个数,最后要保证数组是一个非降数组。

思路:我们从前往后看,拆的条件显然是后一个数小于前一个数,但是这里有一个bug,比如对于a,b,c三个数,我们在访问a的时候,发现b>=a,那么a是不用拆的,但是如果b>c,那么b要拆,拆了前面a和b的关系就不满足了,所以我们不能从前往后判断,那么我们换一下从后往前判断呢?这样显然就可以了,因为前面的数拆了也不影响后面的数大于等于它的条件。还有一个容易忽略的点在于这个数拆了之后,自身的两个数是不满足条件的,一定要记得判断。

#include<bits/stdc++.h>
using namespace std;
int a[100];
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		int last=a[n];
		int flag=1;
		for(int i=n-1;i>=1;i--)
		{
			if(last>=a[i]) last=a[i];
			else
			{
				//a[i]可能只有一位
				//a[i]自己拆完不满足
				if(a[i]%10>last || a[i]/10==0 || a[i]/10>a[i]%10) 
				{
					flag=0;
					break;
				}
				else last=a[i]/10;
			}
		}
		if(flag) printf("YES\n");
		else printf("NO\n");
	}
}

C. Arrow Path(Problem - C - Codeforces

题目大意:现在有一个2行n列的矩阵,矩阵的每一格都有一个向左或者向右的方向,机器人最开始在(1,1)位置,它每次可以向上下左右四个方向移动,移动之后又会按照当前格中的方向进行移动,问最后它能否到达(2,n)位置。

思路:对于这种操作,那么我们就需要看哪些操作是有效的,哪些操作是无效的。显然,如果它向右移,然后右边的格子的字符是向左,那不管它怎么向右移动都是无效的。那么对于向下操作呢,显然也需要它下面的那一个是向右的,否则,它就会被送到左下格,往前就是无效操作,往上要么被往左送,要么又回到刚刚下来的位置。对于向上操作,也是一样,上面那一格一定要是向右的,我原本觉得向上操作是没必要的,但实际上如果两行交替着出现向左的格子,那么可以一会儿上一会儿下的避开。往左操作就真的是无效的了。

#include<bits/stdc++.h>
using namespace std;
char s[3][200010];
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n;
		scanf("%d",&n);
		scanf("%s%s",s[1]+1,s[2]+1);
		int x=1,y=1;
		while(!(x==2&&y==n))
		{
			if((x==2&&y+1==n)||(x==1&&y==n))break;
			if(s[x][y+1]=='>')y+=2;
			else//这里是向右不能移动,只能向上或者向下移动的情况,如果还不行,那么确实移动不到
			{
				x+=1;
				if(x==3) x=1;
				if(s[x][y]=='>') y+=1; 
				else break;
			}
		}
		if(x==2&&y==n) printf("YES\n");
		else printf("NO\n");
	}
}

D. Tandem Repeats?(Problem - D - Codeforces

题目大意:给定一个字符串,我们需要找到最长的偶数长子串,使得子串的前半段完全等于后半段。问这样的子串最长有多长。

思路:这题说前半段等于后半段,我还以为是kmp,但比赛那会儿时间太紧了,没写出来,比赛结束后才发现我高看它了,根本就用不着kmp,我们只要枚举子串一半的长度,对于每个长度从s的第一个字符开始找,s[i]=s[i+k]就将计数的变量+1,否则就将计数的变量置为0,一旦计数的变量等于k,那么就说明对于这个长度我们找到了一个合法的子串,这样一直往后枚举,最后就能得到最长的长度。

#include<bits/stdc++.h>
using namespace std;
char s[200010];
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%s",s+1);
		int cnt=0;
		int n=strlen(s+1);
		for(int k=1;k*2<=n;k++)
		{
			int c=0;
			for(int i=1;i+k<=n;i++)
			{
				if(s[i]==s[i+k]||s[i]=='?'||s[i+k]=='?') c++;
				else c=0;
				if(c==k) cnt=k;
			}
		}
		printf("%d\n",cnt*2);
	}
}
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值