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

目录

1.A - Frequency

2.B - Leftover Recipes

3.C - We Got Everything Covered!

4.D - A Balanced Problemset?

5.E - Lame King

6.F - Grid Ice Floor


1.A - Frequency

B - 频率 (atcoder.jp)

问题描述

给定一个由小写英文字母组成的字符串 S。找出 S 中出现次数最多的字符。如果有多个出现次数相同的字符,则报告字母表顺序最早的那个。

限制条件

  • 1≤∣S∣≤1000(∣S∣ 为字符串 S 的长度。)
  • S 中的每个字符都是小写英文字母。

输入

输入一个字符串S

输出

在出现次数最多的字符中,打印字母表顺序最早的那个。

示例 1

InputcopyOutputcopy
frequency
e

示例 2

InputcopyOutputcopy
atcoder
a

示例 3

InputcopyOutputcopy
pseudopseudohypoparathyroidism
o

这道题可以用一个数组存下每个字符出现的次数,用一个值存下最大出现次数,再从数组前面往后面遍历,若有出现次数与最多次一样的直接输出这个字符。

#include<bits/stdc++.h>
using namespace std;
int dp[30];
int main()
{
	string a;
	cin>>a;
	for(int i=0;i<a.size();i++){
		dp[a[i]-'a']++;//计数
	}
	int mx=-1;
	for(int i=0;i<30;i++){
		mx=max(mx,dp[i]);//找出现最多次数
	}
	for(int i=0;i<=30;i++){
		if(dp[i]==mx)//按照顺序表,先找到的就是我们的答案
		{
			printf("%c",i+'a');
			return 0;
		}
	}
	return 0;
}

2.B - Leftover Recipes

C - 剩菜食谱 (atcoder.jp)

题目描述

你的冰箱里有N种食材。我们将它们称为食材1、……和食材N。你有Qi​克的食材i。

你可以制作两种菜肴。制作一份A菜,你需要每种食材i (1≤i≤N)克。制作一份B菜,你需要每种食材克。你只能制作整数份的每种菜肴。

只使用冰箱里的食材,你能制作的菜肴总份数最多是多少?

限制条件

  • 1≤N≤10
  • 1≤Qi​≤10^6
  • 0≤Ai​≤10^6
  • 存在i使得1Ai​≥1。
  • 0≤Bi​≤10^6
  • 存在i使得Bi​≥1。
  • 所有输入值均为整数。

输入

输入以以下格式从标准输入给出:

N
Q1​ Q2​ …… QN​
A1​ A2​ …… AN​
B1​ B2​ …… BN​

示例1

InputcopyOutputcopy
2
800 300
100 100
200 10
5

示例2

InputcopyOutputcopy
2
800 300
100 0
0 10
38

示例3

InputcopyOutputcopy
2
800 300
801 300
800 301
0

示例4

InputcopyOutputcopy
10
1000000 1000000 1000000 1000000 1000000 1000000 1000000 1000000 1000000 1000000
0 1 2 3 4 5 6 7 8 9
9 8 7 6 5 4 3 2 1 0
222222

这道题的思路是,先算出做第一道菜最多可以做多少盘,需要用每种材料除以做第一道菜需要的每种材料的量,找到一个最小值,就是最多能做第一道菜的盘数,最后在一次遍历,当少做n盘第一道菜(n<=最多做第一道菜的盘数),剩下的材料可以做多少盘第二道菜,更新最多盘数,得到最优解。

#include<bits/stdc++.h>
using namespace std;
int num,n[30],a[30],b[30];
int ans;
int main(){
	cin>>num;
	for(int i=1;i<=num;i++)cin>>n[i];
	for(int i=1;i<=num;i++)cin>>a[i];
	for(int i=1;i<=num;i++)cin>>b[i];
	
	int m1=1e9,m2;
	for(int i=1;i<=num;i++)//找第一盘菜最多做多少份 
		if(a[i]>0)//a[i]可能为0,所以要特判 
		m1=min(m1,n[i]/a[i]);
	for(int x=0;x<=m1;x++){//=依次遍历 
		m2=1e9;
		for(int i=1;i<=num;i++)
			if(b[i]>0)
			m2=min(m2,(n[i]-a[i]*x)/b[i]);//剩余材料最多做几盘第二道菜 
		ans=max(ans,x+m2);//更新最优解 
	}
	cout<<ans;
	return 0;
} 

3.C - We Got Everything Covered!

Problem - 1925A - Codeforces

题目描述

给定两个正整数 n 和 k。

你的任务是找到一个字符串 s,使得使用前 k个小写英文字母可以组成的长度为 n的所有可能字符串都是 s 的子序列。

如果有多个答案,输出长度最小的。如果仍然有多个答案,可以输出任意一个。

注意:如果一个字符串 a可以通过从 b 中删除一些(可能为零)字符而不改变剩余字符的顺序得到字符串 a,那么 a 就是 b的子序列。

输入

输入的第一行包含一个整数 t (1≤t≤676),表示测试用例的数量。

每个测试用例包括一行输入,包含两个整数 n (1≤n≤26) 和 k (1≤k≤26)。

输出

对于每个测试用例,输出一行,包含一个字符串 s,满足上述条件。如果有多个答案,输出长度最小的。如果仍然有多个答案,可以输出任意一个。

示例 1

InputcopyOutputcopy
4
1 2
2 1
2 2
2 3
ab
aa
baab
abcbac

这道题题目意思很难搞懂,意思就是在26个字母里面的前k个字母,任意取n个字母,组成字符串,这些字符串都能与某个字符串的子串对应,我们的目的就是输出这个字符串,有多个答案,我们输出任意一个即可。

听着很难,其实只需要输出n次前k个字母,我也很懵逼,就过后面模拟一下才恍然大悟。

原来是我忘记看注意了,只要不改变顺序,删除部分也可以。

#include<bits/stdc++.h>
using namespace std;
int main()
{
   
    int t;
    cin>>t;
    while(t--)
    {
        int n,k;
        cin>>n>>k;
        for(int i=0;i<n;i++)
        for(int j=0;j<k;j++)
        printf("%c",'a'+j);   
        printf("\n"); 
    }
    return 0;
}

4.D - A Balanced Problemset?

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

题目描述

Jay设法创建了一个难度为x
的问题,并决定将其作为Codeforces Round #921的第二个问题。

但Yash担心这个问题会使比赛失衡,协调员会拒绝它。因此,他决定将它拆分成一个包含n个子问题的问题集,使得所有子问题的难度都是正整数,且它们的和等于x。

协调员Aleksey将问题集的平衡定义为问题集中所有子问题的难度的最大公约数。

找出Yash可以实现的问题集最大平衡,如果他选择子问题的难度最优。

输入

输入的第一行包含一个整数t(1≤t≤10^3),表示测试用例的数量。

每个测试用例包含一行输入,包含两个整数x(1≤x≤10^8)和n(1≤n≤x)。

输出

对于每个测试用例,输出一行,包含一个整数,表示Yash可以实现的问题集最大平衡。

示例1

InputcopyOutputcopy
3
10 3
5 5
420 69
2
1
6

这道题是将数x分成n份,找出这n个数的最大因数。

需要找到x的所有因子,如果这个因子去除x,得到的值>=n,那么证明这个因子合适。

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        int x, n;
        cin >> x >> n;
        int a[1000], b = 0;
        for (int i = 1; i * i <= x; i++)
        {
            if (x % i == 0)
            {
                a[++b] = i;//存入因子 
                if (i != x / i) //由于循环停止条件是i*i>x,所以因子不能存下x本身,如果n为1,后续就不能找出最优解 
                    a[++b] = x / i;
            }
        }
        int ans = 1;//答案最小都为1 
        for (int i = 1; i <= b; i++)
        {
        	cout<<a[i]<<" ";
            if (x / a[i] >= n)//可以分 
                ans = max(ans, a[i]);//将次因子与答案比较,更新最优答案 
        }
        cout << ans << endl;
    }
    return 0;
}

5.E - Lame King

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

题目描述

给定一个大小为201×201的棋盘,即有201行和201列。棋盘的行从下到上编号为−100到100。盘的列从左到右编号为−100到100。记号(r,c)表示位于第r行和第c列的格子。

在位置(0,0)有一个国王棋子,它想尽快到达位置(a,b)。在这个问题中,我们的国王很笨。每秒钟,国王只能进行以下五种移动之一。

跳过。国王的位置保持不变。向上移动。如果国王当前的位置是(r,c),它将移动到位置(r+1,c)。
向下移动。位置从(r,c)变为(r−1,c)。
向右移动。位置从(r,c)变为(r,c+1)。
向左移动。位置从(r,c)变为(r,c−1)。
国王不允许进行使其超出棋盘范围的移动。国王之所以笨是因为他不允许连续两秒钟进行相同的移动。例如,如果国王向右移动,下一秒他只能跳过、向上、向下或向左移动。国王需要多少秒钟才能到达位置(a,b)?

输入

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

每个测试用例由两个整数a和b(−100≤a,b≤100)组成,表示国王想要到达的格子的位置。保证a≠0或b≠0。

输出

输出t个整数。第i个整数应该等于国王在第i个测试用例中到达目标位置所需的最少秒数。国王始终从位置(0,0)开始。

示例 1

输入copy输出copy
5
-4 1
4 4
0 -6
-5 -4
7 -8
7
8
11
9
15

这道题其实只需要计算一下就行,测试中还想着用搜索算法去解决。

直接贪心一下,因为不能连续执行两次相同的动作,所以跳过一下是需要的,只要找出需要跳过几次就行。

曲折走时,不用跳过,这也是贪心的一步,当需要直行时就需要跳过了,所以只要计算一下就行。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    cin>>t;
	while(t--)
    {
        int ex,ey;
        cin>>ex>>ey;
        if(abs(ex)>abs(ey)) 
		cout<<abs(ey)*2+(abs(ex)-abs(ey))*2-1<<endl;
		else if(abs(ex)<abs(ey))
		cout<<abs(ex)*2+(abs(ey)-abs(ex))*2-1<<endl;
        else
        cout<<abs(ex)*2<<endl;
    }
    return 0;
}

6.F - Grid Ice Floor

D - 网格冰地板 (atcoder.jp)

题目描述

有一个 N×M网格和一个站在上面的玩家。让 (i,j) 表示该网格中第  i 行从顶部开始数的方块和第 j 列从左边开始数的方块。该网格的每个方块都是冰或石头,用  N 长度为  M 的字符串表示如下

如果   S i​  的第  j 个字符是 .,则方块 (i,j) 是冰;

如果   S i的第 j 个字符是 #,则方块 (i,j) 是石头。

此网格的外围(第 1 行、第 N 行、第 1 列、第 M 列中的所有方块)是石头。

最初,玩家站在冰块 ((2,2) 上。

玩家可以进行以下移动零次或多次。

首先,指定移动方向:上、下、左或右。
然后,沿着该方向移动,直到玩家碰到石头。具体来说,继续执行以下操作:
如果移动方向上的下一个方块是冰块,则去到该方块并继续移动;
如果移动方向上的下一个方块是石头,则留在当前方块并停止移动。
找出玩家可以触及(经过或停留在)的冰块数量。

约束条件

3≤N,M≤200  

S i是长度为  M 的字符串,由 # . 组成。

如果i=1、i=N、j=1 或 j=M,则方块 (i,j) 是石头。

方块 (2,2) 是冰。

输入

输入以以下格式从标准输入给出:

N M
S1​
S2​
⋮⋮
SN​

输出

以整数形式输出答案。

示例 1

InputcopyOutputcopy
6 6
######
#....#
#.#..#
#..#.#
#....#
######
12

示例 2

InputcopyOutputcopy
21 25
#########################
#..............###...####
#..............#..#...###
#........###...#...#...##
#........#..#..#........#
#...##...#..#..#...#....#
#..#..#..###...#..#.....#
#..#..#..#..#..###......#
#..####..#..#...........#
#..#..#..###............#
#..#..#.................#
#........##.............#
#.......#..#............#
#..........#....#.......#
#........###...##....#..#
#..........#..#.#...##..#
#.......#..#....#..#.#..#
##.......##.....#....#..#
###.............#....#..#
####.................#..#
#########################
215

一道搜索题目,只不过这个不撞南墙不回头版,只要往一个方向走,不撞到‘#’,那就一直往这个方向走。

#include<bits/stdc++.h>
using namespace std;
char a[250][250];
int v[250][250] = {0}, vk[250][250];
int dx[] = {0, -1, 0, 1};
int dy[] = {1, 0, -1, 0};
int ans;
struct node {
    int x, y;
} k;
int main() {
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            cin >> a[i][j];
    v[2][2] = 1;
    vk[2][2] = 1;
    k.x = 2, k.y = 2;
    queue<node> q;
    q.push(k);
    while (!q.empty()) {
        node h = q.front();
        q.pop();
        for (int i = 0; i < 4; i++) {
            int tx = h.x ;
            int ty = h.y ;
            if (a[tx][ty] == '#') continue;
            while (a[tx+dx[i]][ty+dy[i]] == '.') {//不到#就一直在 
                tx += dx[i], ty += dy[i];
                vk[tx][ty] = 1;//设置为经过,用与后面统计 
            }
            if (!v[tx][ty]) {//将不能继续走的点入队 
                v[tx][ty] = 1;
                q.push({tx, ty});
            }
        }
    }
    for (int i = 0; i < 250; i++) {
        for (int j = 0; j < 250; j++) {
            if (vk[i][j]) ans++;//统计 
        }
    }
    cout << ans << endl;//输出 
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值