hope实验室预备役第一次测试题解

目录

1.  A - Rook

2. B - Satisfying Constraints

3. C - Sending Messages

4.D - Infinite Replacement

5.E - Also Try Minecraft

6.F - Summation Game

7.G - Very Different Array


1.  A - Rook

https://codeforces.com/problemset/problem/1907/A

你可能知道,国际象棋是一种在一个排列成8x8网格的棋盘上进行的游戏。这个棋盘的列用从a到h的字母标记,行用从1到8的数字标记。每个方格由它所属的行和列来描述。

hope实验室预备役第一次测试题解_第1张图片

车是国际象棋中的一个棋子。在它的回合中,它可以水平或垂直地移动任意非零数量的方格。你的任务是找出车在空棋盘上所有可能的移动方式。

输入

输入的第一行包含一个整数t(1≤t≤64)测试用例的数量。接下来是每个测试用例的描述。每个测试用例包含一个由两个字符组成的字符串,描述了车所在的方格。第一个字符是从ah的字母,表示列的标记,第二个字符是从18的数字,表示行的标记。相同的位置可能出现在多个测试用例中。

输出

对于每个测试用例,以与输入相同的格式输出车可以移动到的所有方格的描述。你可以以任何顺序输出每个测试用例中的方格。

示例 1

Inputcopy Outputcopy
1
d5
d1
d2
b5
g5
h5
d3
e5
f5
d8
a5
d6
d7
c5
d4

由于这道题目要求我们用任意顺序输出车可以移动到的方格,那么这道题就只需我们将这个棋盘用一个二维矩阵模拟,它的行是8 7 6 5 4 3 2 1,那么我们可以自定义一个函数,将对应输入得到1 2 3 4 5 6 7 8。

int f(int n)
{
	int a[]={0,8,7,6,5,4,3,2,1};
	return a[n];
}

a b c d e f g h i 只需减去字符a的码值再+1就行了。

下面是个人代码,应该还有更好的办法

#include
using namespace std;
int f(int n)
{
	int a[]={0,8,7,6,5,4,3,2,1};
	return a[n]; 
}
int main()
{
	int t;
	cin>>t;
	int temp=t;
	while(temp--){
		char a[2];
		cin>>a;
		int startx=a[1]-48;
		int starty=a[0]-96;
		for(int i=1;i<=8;i++){
			for(int j=1;j<=8;j++){
				if((f(i)==startx||j==starty)&&((f(i)==startx&&j!=starty)||(f(i)!=startx&&j==starty))) 
				{//这里需要行或列其中一个与输入方格相同的,但是不同都相同 
					char p=j+96;//加上96得到对应的字母 
					printf("%c%d\n",p,f(i));
				}
			}
		}
	}
	return 0;
}

2. B - Satisfying Constraints

https://codeforces.com/problemset/problem/1920/A

Alex正在解决一个问题。他对整数 k 有 n 个约束条件。约束条件有三种类型:

  1. k 必须 大于或等于 某个整数 x;
  2. k 必须 小于或等于 某个整数 x;
  3. k 必须 不等于 某个整数 x。

帮助Alex找出满足所有 n 约束条件的整数 k 的数量。保证答案是有限的(至少存在一种 1 类型的约束条件和至少一种 2 类型的约束条件)。同时保证没有两个约束条件完全相同。

输入

每个测试包含多个测试用例。第一行包含一个整数 t (1≤t≤500) —— 测试用例的数量。接下来是测试用例的描述。每个测试用例的第一行包含一个整数 n (2≤n≤100) —— 约束条件的数量。接下来的 n 行描述了约束条件。每行包含两个整数 a 和 x (a∈{1,2,3},1≤x≤109)。 a 表示约束条件的类型。如果是 a=1,则 k必须大于或等于 x。如果是 a=2,则 k 必须小于或等于 x。如果是 a=3,则 k必须不等于 x。

保证存在有限数量的整数满足所有 n 约束条件(至少存在一种 1 类型的约束条件和至少一种 2 类型的约束条件)。同时,保证没有两个约束条件完全相同(换句话说,所有的 (a,x)对都是不同的)。

输出

对于每个测试用例,输出一个整数 —— 满足所有 n约束条件的整数 k 的数量。

示例 1

Inputcopy Outputcopy
6
4
1 3
2 10
3 1
3 5
2
1 5
2 4
10
3 6
3 7
1 2
1 7
3 100
3 44
2 100
2 98
1 3
3 99
6
1 5
2 10
1 9
2 2
3 2
3 9
5
1 1
2 2
3 1
3 2
3 3
6
1 10000
2 900000000
3 500000000
1 100000000
3 10000
3 900000001
7
0
90
0
0
800000000

我们先设置好k的取值范围为1-10^9,然后每次操作收缩取值的边界,当a=3时,用一个数组记录这时的x值,到后面判断是否在这个范围内即可。

下面是AC代码

#include
using namespace std;
int main()
{
	int t;
	cin>>t;
	while(t--){
		long long n;
		cin>>n;
		long long l=1,r=1e9,ans=0;//每次开始时的范围都是1-10^9 
		int k[700],b=0;
		while(n--){
			long long a,x;
			cin>>a>>x;
			if(a==1)//当新的上限大于当前上限,更新上限	
			l=max(l,x); 
			else if(a==2)//当新的下限小于当前下限,更新下限 
			r=min(r,x);
			else
			k[++b]=x;//记录	
		}
		if(l>r)//取值范围不合理,输出0 
		cout<<0<=l&&k[i]<=r)
				ans++;
			}
			cout<

3. C - Sending Messages

https://codeforces.com/problemset/problem/1921/C

 斯特潘是一个非常忙碌的人。今天他需要在时刻m1,m2,…mn(mi

手机每工作单位时间会消耗a单位的电量。此外,斯特潘可以随时关闭手机,稍后再打开。每次这样做会消耗b单位的能量。考虑到开关机是瞬间完成的,所以你可以在时刻x打开手机并发送消息,反之亦然,在时刻x发送消息并关闭手机。

如果在任何时刻电量降到0(变成≤0),就无法在那时刻发送消息。

由于所有消息对斯特潘来说都非常重要,他想知道是否能在不充电的情况下发送所有消息。

输入

输入的第一行包含一个整数t(1≤t≤104)— 测试用例的数量。接下来是每个测试用例的描述。

每个测试用例的第一行包含四个整数n、f、a和b(1≤n≤2⋅105、1≤f,a,b≤109)— 消息数量、初始手机电量、单位时间电量消耗和连续开关机消耗。

每个测试用例的第二行包含n个整数m1,m2,…,mn(1≤mi≤109、mi

保证在一个测试中n的总和不超过2x10^5。

输出

对于每个测试用例,如果斯特潘能发送所有消息,则输出“YES”,否则输出“NO”。

你可以以任何大小写形式输出每个字母(大写或小写)。例如,字符串“yEs”、“yes”、“Yes”和“YES”都会被接受为肯定答案。

示例 1

Inputcopy Outputcopy
6
1 3 1 5
3
7 21 1 3
4 6 10 13 17 20 26
5 10 1 2
1 2 3 4 5
1 1000000000 1000000000 1000000000
1000000000
3 11 9 6
6 8 10
12 621526648 2585904 3566299
51789 61859 71998 73401 247675 298086 606959 663464 735972 806043 806459 919683
NO
YES
YES
NO
NO
YES


这道题可以贪心找到最佳方式。

下面代码展示

#include
using namespace std;
long long n,f,a,b,xx[200010]={0};
int main()
{
	long long t;
	cin>>t;
	while(t--){
		cin>>n>>f>>a>>b;
		for(int i=1;i<=n;i++) cin>>xx[i];
		sort(xx+1,xx+n+1);//先将需要发送信息的时刻从小到大排序 
		for(int i=1;i<=n;i++){
			if((xx[i]-xx[i-1])*a>b)//当两个需要发送信息的时段内,不关机的掉的电量大于关机掉的电量,总电量就减去掉电少的方式 
			f-=b;
			else //反之减去不关机掉的电量 
			f=f-(xx[i]-xx[i-1])*a;
		}
		if(f>0) cout<<"YES"<

4.D - Infinite Replacement

https://codeforces.com/problemset/problem/1674/C

给一个只含小写字母 a 的字符串 s 和一个用来替换的字符串 t 。

你可以将 s中任意一个字母 a 用 t 来替换,替换的次数不限。

对于每一个 s 和 t ,你可以得到几个不同的字符串?如果有无限个,输出 -1 。

输入

输入的第一行包含一个整数 q(1≤q≤10^4),表示测试数据组数。

对于每组测试数据:第一行包含一个只包含 a 的非空字符串 s,s 的长度不超过 50。

第二行包含一个非空小写英文字符串 t,t 的长度不超过 50,。

输出

对于每组测试数据,输出一个整数,表示你可以得到的不同的字符串数量。如果有无限个不同字符串,输出 -1。

Sample 1

Inputcopy Outputcopy
3
aaaa
a
aa
abc
a
b
1
-1
2

什么情况会出现无数个呢,就是当b字符串里面有字符'a',并且它的长度不为大于1,这时便可以一直套,得到无数个不同的字符串,不然就只会得到一个不同的字符串。

如果b串里面没有字符‘a’那就是,2^n种结果,n为a的长度。

下面代码展示

#include
#include
using namespace std;
int main()
{
	int t;
	cin>>t;
	while(t--){
		string a,b;
		cin>>a>>b;
		int flag=0;
		for(int i=0;i

5.E - Also Try Minecraft

https://codeforces.com/problemset/problem/1709/B

你正在测试新的秘密Terraria更新。这个更新将在游戏中添加任务!

简单来说,世界地图可以表示为长度为n的数组,其中世界的第i列高度为ai。

你有m个任务需要测试。第j个任务由两个整数sj和tj表示。在这个任务中,你需要从第sj列移动到第tj列。在任务开始时,你出现在第sj列。

在一次移动中,你可以从第x列移动到第x−1列或者第x+1列。在这个版本中,你有幽灵靴,可以让你飞行。由于这是测试版本,它们有bug,所以只有在上飞行时才能飞行,并且飞行持续时间无限。当你从高度为p的列移动到高度为q的列时,你会受到一定的坠落伤害。如果高度p大于高度q,你会受到p−q的坠落伤害,否则你会飞起来并受到0的伤害。

对于给定的每个任务,确定你在完成这个任务时可以受到的最小坠落伤害。

输入

输入的第一行包含两个整数n和m(2≤n≤105;1≤m≤10^5)— 世界中的列数和你需要测试的任务数。

输入的第二行包含n个整数a1,a2,…,an(1≤ai≤10^9),其中ai是世界的第i列的高度。接下来的m
行描述了任务。

第j个任务包含两个整数sj和tj(1≤sj,tj≤n;sj≠tj),表示你需要在第j个任务期间从第sj列移动到第tj列。注意sj可能大于tj。

输出

输出m个整数。其中第j个整数应该是在第j个任务完成时你可以受到的最小坠落伤害。

示例 1

Inputcopy Outputcopy
7 6
10 8 9 6 8 12 7
1 2
1 7
4 6
7 1
3 5
4 2
2
10
0
7
3
1

这道题用暴力找会事件超限,所以这道题可以先用前缀和存下答案,到后面输入就直接输出就可以了。

下面代码展示

#include
using namespace std;
long long a[100010],sum1[100010],sum2[100010];//这里需要两个前缀和,一个从前往后,一个从后往前。 
int main()
{
	long long n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=2;i<=n;i++){
		sum1[i]=sum1[i-1]+(max(a[i-1]-a[i],(long long)0));//当后面一列的高度大于前面的,就会坠落,反之,直接得0就行 
	}
	for(int i=n-1;i>=1;i--)
	{
		sum2[i]=sum2[i+1]+(max(a[i+1]-a[i],(long long)0));//同理 
	}
	while(m--){
		int l,r;
		cin>>l>>r;
		if(r>l) cout<

6.F - Summation Game

https://codeforces.com/problemset/problem/1920/B

爱丽丝和鲍勃正在玩一个游戏。 他们有一个数组 a1,a2,…,an。 游戏包括两个步骤:

首先,爱丽丝将从数组中移除 最多 k 个元素。
其次,鲍勃将把数组中的 最多 x个元素乘以 −1。
爱丽丝希望最大化数组元素的和,而鲍勃希望最小化它。找到游戏结束后数组元素的总和,假设两位玩家都采取最优策略。

输入

每个测试包括多个测试用例。第一行包含一个整数 t(1≤t≤104) — 测试用例的数量。接下来是测试用例的描述。

每个测试用例的第一行包含三个整数 n, k, 和 x (1≤n≤2⋅105, 1≤x,k≤n) — 数组中的元素数量,爱丽丝可以移除的元素数量限制,以及鲍勃可以乘以 −1 的元素数量限制。

每个测试用例的第二行包含 n 个整数 a1,a2,…,an (1≤ai≤1000) — 数组的元素。

保证所有测试用例中 n 的总和不超过 2⋅10^5。

输出

对于每个测试用例,输出一个整数 — 假设两位玩家都采取最优策略后,游戏结束后数组元素的总和。

示例 1

Inputcopy Outputcopy
8
1 1 1
1
4 1 1
3 1 2 4
6 6 3
1 4 3 2 5 6
6 6 1
3 7 3 3 32 15
8 5 3
5 5 3 3 3 2 9 9
10 6 4
1 8 2 9 3 3 4 5 3 200
2 2 1
4 3
2 1 2
1 3
0
2
0
3
-5
-9
0
-1

下面代码展示

#include
using namespace std;
#define M 200010
int sum[M];
int a[M];
int main()
{
	int t;
	cin>>t;
	while(t--){
		int n, k, x;
		cin >> n >> k >> x;
		for (int i = 1; i <= n; i ++) cin >> a[i];
		sort(a + 1, a + n + 1);//因为这两个人都会用最优方法,所以排好序方便后面判断 
		for (int i = 1; i <= n; i ++) sum[i] = sum[i - 1] + a[i];//使用前缀和,防止时超限 
		int ans = -1e9;
		if (n == k) ans = 0;//当n等于k时,ans至少都会大于0,所以更新此时最小值,再找是否有更优解法 
		for (int r = max(1, n - k); r <= n; r ++) {
		    int l = max(1, r - x + 1); 
		    int cnt = sum[l - 1] - (sum[r] - sum[l - 1]);//将数组分成两部分,sum[r] - sum[l - 1]为被鲍勃变为负数的元素的和 
		    ans = max(ans, cnt);//更新最优解 
		}
		cout<

7.G - Very Different Array

https://codeforces.com/problemset/problem/1921/D

彼特亚有一个长度为ai的整数数组。他的哥哥瓦西亚嫉妒起来,决定自己也要创建一个长度为n的整数数组。

为此,他找到了m个整数bi(m≥n),现在他想从中选择一些整数,并以特定顺序排列它们,以得到一个长度为n的数组ci。

为了避免与他哥哥相似,瓦西亚希望使他的数组与彼特亚的数组尽可能不同。具体来说,他希望总差异D=∑ni=1|ai−ci|尽可能大。

帮助瓦西亚找到他可以获得的最大差异D。

输入

每个测试包含多个测试用例。第一行包含一个整数t(1≤t≤100)—测试用例的数量。接下来是测试用例的描述。

每个测试用例的第一行包含两个整数n和m(1≤n≤m≤2⋅10^5)。

每个测试用例的第二行包含n个整数ai(1≤ai≤10^9)。每个测试用例的第三行包含m个整数bi(1≤bi≤10^9)。

保证在一个测试中,所有测试用例的m之和不超过2⋅10^5。

输出

对于每个测试用例,输出一个整数—可以获得的最大总差异D。

示例 1

Inputcopy Outputcopy
9
4 6
6 1 2 4
3 5 1 7 2 3
3 4
1 1 1
1 1 1 1
5 5
1 2 3 4 5
1 2 3 4 5
2 6
5 8
8 7 5 8 2 10
2 2
4 1
9 6
4 6
8 10 6 4
3 10 6 1 8 9
3 5
6 5 2
1 7 9 7 2
5 5
9 10 6 3 7
5 9 2 3 9
1 6
3
2 7 10 1 1 5
16
0
12
11
10
23
15
25
7

这道题需要对两个数组先排序,再分别用两个变量表示这两数组的头和尾,最后分别比较看那一组差异大,取那一组,再收缩边界即可。

下面代码展示

#include
using namespace std;
long long a[200010],b[200010];
int main()
{
	int t;
	cin>>t;
	while(t--){
		int n,m;
		long long ans=0;
		cin>>n>>m;
		for(int i=1;i<=n;i++) cin>>a[i];
		for(int i=1;i<=m;i++) cin>>b[i];
		sort(a+1,a+n+1);//排序 
		sort(b+1,b+m+1);
		long long l=1,r=n,l1=1,r1=m;
		while(l<=r&&l1<=r1){//当某一个数组的头尾重合时,停止 
			if(abs(a[l]-b[r1])>abs(a[r]-b[l1]))//比较第一个数组的头和第二个数组的尾的差异和第二个数组的头和第一个数组的尾的差异 
			{
				ans+=abs(a[l]-b[r1]);//添加最优 
				l++,r1--;//边界收缩 
			}
			else
			{
				ans+=abs(a[r]-b[l1]);//同理..... 
				r--,l1++;
			}
		}
		cout<

题解到此结束

本篇完~

你可能感兴趣的:(算法,c++)