ABC 458 (from ACcoder)

ABC 458部分题解

题目:https://atcoder.jp/contests/abc458/tasks

A_chompers


题目翻译

您将得到一个字符串 \(S\) ,该字符串由小写英文字母和一个正整数 \(N\) 组成。 \(S\) 的长度至少为 \(2N+1\) 。查找通过从 \(S\) 的开头删除 \(N\) 个字符并从其结尾删除 \(N\) 个字符而获得的字符串。

例子:

Sample Input

复制代码
chemotherapy
3

Sample Output

复制代码
mother

Removing the first three characters (che) and the last three characters (apy) from chemotherapy gives mother.

解释:

删去前3个字符(che),删去后3个字符(apy)

得到(che)mother(apy)

得到答案:

复制代码
mother

思路讲解


显然地,很多人下意识会按照题目的描述去做,即模拟从头和尾上删去n个字符

但是,c++的语法中并没有简单的reduce和add函数,即使是使用STL的string

也要考虑到-+的重载。

于是我们考虑:有没有简便的写法?

既然删不了字符,那就不删了,直接选择从第n个字符输出到第len-n个字符就好了,

这样就等效于删去了前n个和后n个字符,而避免了使用运算符的麻烦
注:若stirng s的字符串长度为len,则该字符串的每个字符分别为s[0]~s[len-1]

Accode:


c++ 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
string s;
int n;
int main()
{
	ios::sync_with_stdio(0);
	cin>>s>>n;
	int l=s.size();
	for(int i=n;i<l-n;i++) cout<<s[i];
	return 0;
}
//Author:AAA_jiancaipifa

B_Count Adjacent Cells


题目翻译

有一个包含 \(H\) 行和 \(W\) 列的网格。从上数第 \(i\) 行和从左数第 \(j\) 列的单元格表示为单元格 \((i, j)\) 。当 \(|x_1 - x_2| + |y_1 - y_2| = 1\) 时,称单元格 \((x_1, y_1)\) 和 \((x_2, y_2)\) 是边相邻的 。对于每个单元格,找出与其边缘相邻的单元格的数量。

例子:

Sample Input 1

复制代码
4 5

Sample Output 1

复制代码
2 3 3 3 2
3 4 4 4 3
3 4 4 4 3
2 3 3 3 2

解释:

四个顶点都有2个相邻的点

四条边都有3个相邻的点

中间的点都有4个相邻的点

思路讲解


这题最阴的地方就是h和w特殊值的特判!!!

1.h=1 and w=1

显然没有相邻,答案是0

2.h=1 and w>1

只有一行,首尾都只有一个相邻,为1;中间都有两个相邻,为2

3.h>1 and w=1

只有一列,同上

4.h>1 and w>1

这种情况才是普遍情况:

位于最边角的四个点只有两个方向有相邻,所以四个顶点的值均为2

位于边上(不包含顶点)的点都有三个相邻,所以边上的值均为3

中间的点全都有四个相邻,所以中间的点值全为4

知道了以上信息,写出代码就不难了

ACcode:


c++ 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=55;
int ans[N][N];
int h,w;
int main()
{
	ios::sync_with_stdio(0);
	cin>>h>>w;
	if(h==1 and w==1) ans[1][1]=0;
	else if(h==1 and w>1)
	{
		for(int i=1;i<=w;i++)
			if(i==1 or i==w) ans[1][i]=1;
		else ans[1][i]=2;
	}
	else if(h>1 and w==1)
	{
		for(int i=1;i<=h;i++)
			if(i==1 or i==h) ans[i][1]=1;
			else ans[i][1]=2;
	}
	else
	{
		for(int i=1;i<=h;i++)
			for(int j=1;j<=w;j++){
				int tmp;
				if((i==1 or i==h) and (j==1 or j==w)) tmp=2;
				else if(i==1 or i==h or j==1 or j==w) tmp=3;
				else tmp=4;
				ans[i][j]=tmp;
			}
	}
	for(int i=1;i<=h;i++){
		for(int j=1;j<=w;j++)
			cout<<ans[i][j]<<" ";
		cout<<endl;
	}
	return 0;
}
//Author:AAA_jiancaipifa

C_Stands for Center


题目翻译

您将得到一个由大写英文字母组成的字符串 \(S\) 。 找出 \(S\) 中满足以下所有条件的子串(连续子序列)的数目。-它由奇数个字符组成。-它的中间字符是" C "。更正式地说,如果提取的子字符串由 \(l\) 个字符组成,则其第 \(((l+1)/2)\) 个字符为" C "。即使两个子串作为字符串是相同的,如果它们是从不同的位置提取的,它们也会被单独计数。

例子:

Sample Input 1

复制代码
ABCCA

Sample Output 1

复制代码
5

解释:

复制代码
C
BCC
ABCCA
C
CCA

五种

思路解析

对于每个字符c

题目意思即为将c看成某个子串的中间字符。设c的位置为i,那么以它为中心,长度为奇数的子串可以表示为i-k~i+k,k>=0。这样的子串长度为2

k+1,中间字符就是i。为了保证子串在字符串的范围内,需要i-k>=0,i+k<n,即k<=min(i,n-i-1)。因此,对于每个c,可能的k有min(i,n-i-1)+1个,对应满足条件的子串个数。

将所有的子串数相加即可。

ACcode:

c++ 复制代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
string s;
ll ans=0;
int main()
{
	cin>>s;
	int len=s.size();
	for(int i=0;i<len;i++)
		if(s[i]=='C')
			ans+=min(i,n-i-1)+1;
	cout<<ans<<endl;
	return 0;
}
//Author:AAA_jiancaipifa

由于个人能力原因,D E F G题目前我无力解题,谅解一下谢谢