目录
3.C - We Got Everything Covered!
1.A - Frequency
问题描述
给定一个由小写英文字母组成的字符串 S。找出 S 中出现次数最多的字符。如果有多个出现次数相同的字符,则报告字母表顺序最早的那个。
限制条件
- 1≤∣S∣≤1000(∣S∣ 为字符串 S 的长度。)
- S 中的每个字符都是小写英文字母。
输入
输入一个字符串S
输出
在出现次数最多的字符中,打印字母表顺序最早的那个。
示例 1
Inputcopy | Outputcopy |
---|---|
frequency | e |
示例 2
Inputcopy | Outputcopy |
---|---|
atcoder | a |
示例 3
Inputcopy | Outputcopy |
---|---|
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
题目描述
你的冰箱里有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
Inputcopy | Outputcopy |
---|---|
2 800 300 100 100 200 10 | 5 |
示例2
Inputcopy | Outputcopy |
---|---|
2 800 300 100 0 0 10 | 38 |
示例3
Inputcopy | Outputcopy |
---|---|
2 800 300 801 300 800 301 | 0 |
示例4
Inputcopy | Outputcopy |
---|---|
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!
题目描述
给定两个正整数 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
Inputcopy | Outputcopy |
---|---|
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
Inputcopy | Outputcopy |
---|---|
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
题目描述
有一个 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
Inputcopy | Outputcopy |
---|---|
6 6 ###### #....# #.#..# #..#.# #....# ###### | 12 |
示例 2
Inputcopy | Outputcopy |
---|---|
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;
}