A. Problem Generator
时间限制:1秒 空间限制:256MB 输入:标准输入 输出:标准输出
问题描述
Vlad 计划在下个月举行 m 轮比赛。每一轮比赛应包含一个难度等级为 'A', 'B', 'C', 'D', 'E', 'F', 'G' 的问题。
Vlad 已经有一个包含 n 道问题的题库,其中第 i 道问题的难度等级为 。这些问题可能还不够,因此他可能需要想出更多的问题。
Vlad 想尽可能少地新增问题,所以他请求你帮忙找到为了举行 m 轮比赛他需要新增的最少问题数。
例如,如果 m = 1, n = 10, a = 'BGECDCBDED',那么他需要新增两个问题:一个难度等级为 'A' 的问题和一个难度等级为 'F' 的问题。
输入格式
第一行包含一个整数 t () ,表示测试用例的数量。
每个测试用例的第一行包含两个整数 n 和 m (,) ,表示题库中的问题数量和即将进行的比赛轮数。
每个测试用例的第二行包含一个长度为 n 的字符串 a,字符从 'A' 到 'G',表示题库中每个问题的难度等级。
输出格式
对于每个测试用例,输出一个表示为了举行 m 轮比赛需要新增的最少问题数的整数。
输入样例
输出样例
思路
读入的时候统计各种难度的数量,数量少于 m 的,统计少了多少。
代码
#include <bits/stdc++.h>
using namespace std;
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int main() {
int t = read();
while (t--) {
int vis[10];
memset(vis, 0, sizeof(vis));
int n = read(), m = read();
string s;
cin >> s;
for (int i = 0; i < s.length(); i++) vis[s[i] - 'A']++;
int num = 0;
for (int i = 0; i <= 'G' - 'A'; i++) {
if (vis[i] < m) num += m - vis[i]; // 统计个数
}
cout << num << endl;
}
return 0;
}
B. Choosing Cubes
时间限制:1秒 空间限制:256MB 输入:标准输入 输出:标准输出
问题描述
Dmitry 有 n 个方块,从左到右编号从 1 到 n。编号为 f 的方块是他最喜欢的。
Dmitry 把所有的方块都扔到了桌子上,第 i 个方块显示的值是 ()。之后,他将方块按值从大到小排序。如果两个方块显示相同的值,它们可以按任意顺序排列。
排序后,Dmitry 移除了前 k 个方块。然后他想知道他是否移除了他最喜欢的方块(注意,排序后它的位置可能会发生变化)。
例如,如果 n = 5,f = 2,a = [4,3,3,2,3](最喜欢的方块以绿色突出显示),并且 k = 2,可能会发生以下情况:
- 排序后 a = [4,3,3,3,2],由于最喜欢的方块最终位于第二位置,它将被移除。
- 排序后 a = [4,3,3,3,2],由于最喜欢的方块最终位于第三位置,它不会被移除。
输入格式
第一行包含一个整数 t (),表示测试用例的数量。接下来是每个测试用例的描述。
每个测试用例的第一行包含三个整数 n, f 和 k (),表示方块的数量,Dmitry 最喜欢的方块的编号,以及被移除的方块数量。
每个测试用例的第二行包含 n 个整数 (),表示方块上显示的值。
输出格式
对于每个测试用例,输出一行答案——如果方块在所有情况下都会被移除,输出 "YES";如果在任何情况下都不会被移除,输出 "NO";如果可能被移除也可能未被移除,输出 "MAYBE"。
你可以用任何大小写形式输出答案。例如,"YES", "nO", "mAyBe" 都是正确答案。
输入样例
输出样例
思路
分别记下大于第 f 位和等于第 f 位的数的数量,根据数量关系判断(具体看代码)。
代码
#include <bits/stdc++.h>
using namespace std;
int t, n, f, k, a[105];
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int main() {
t = read();
while (t--) {
n = read(), f = read(), k = read(); int num1 = 0, num2 = 0;
for (int i = 1; i <= n; i++) a[i] = read();
for (int i = 1; i <= n; i++) {
if (a[i] > a[f]) num1++;
else if (a[i] == a[f]) num2++;
}
if (num1 + num2 <= k) printf("YES\n");
else if (num1 >= k) printf("NO\n");
else printf("MAYBE\n");
}
return 0;
}
C. Sofia and the Lost Operations
时间限制:2秒 空间限制:256MB 输入:标准输入 输出:标准输出
问题描述
Sofia 有一个包含 n 个整数的数组 。有一天她感到无聊,于是决定依次对这个数组进行 m 次修改操作。
每个修改操作由一对数字 描述,意思是将数组中下标为 的元素赋值为 ,即执行赋值 。在依次应用所有修改操作之后,Sofia 丢弃了最终得到的数组。
最近,你发现了一个包含 n 个整数的数组 。你对这个数组是否是 Sofia 的数组感兴趣。你知道原始数组的值 ,以及修改操作中的值 。然而,值 丢失了。
是否存在一组序列 ,使得依次应用修改操作 到数组 上可以将其变换为数组 ?
输入格式
第一行包含一个整数 t (),表示测试用例的数量。
接下来是每个测试用例的描述。
每个测试用例的第一行包含一个整数 n (),表示数组的大小。
每个测试用例的第二行包含 n 个整数 (),表示原始数组的元素。
每个测试用例的第三行包含 n 个整数 (),表示发现的数组的元素。
第四行包含一个整数 m (),表示修改操作的数量。
第五行包含 m 个整数 (),表示每个修改操作保存的值。
保证所有测试用例中所有 n 值的总和不超过 ,同样所有测试用例中所有 m 值的总和不超过 。
输出格式
输出 t 行,每行是对应测试用例的答案。如果存在合适的序列 ,输出 "YES",否则输出 "NO"。
答案可以以任何大小写形式输出(例如,字符串 "yEs", "yes", "Yes" 和 "YES" 都是正确答案)。
输入样例
输出样例
思路
分别判断 d[m] 是否出现在 b 数组里面以及 b 数组与 a 数组不同的值是否能在 d 数组里面找到。
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 10;
int t, n, m, a[N], b[N], d[N], vis[N];
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
signed main() {
t = read();
while (t--) {
n = read(); int flag = 0;
for (int i = 1; i <= n; i++) a[i] = read();
for (int i = 1; i <= n; i++) b[i] = read();
m = read(); for (int i = 1; i <= m; i++) d[i] = read();
int p = 0;
for (int i = 1; i <= n; i++) {
if (a[i] != b[i]) vis[++p] = b[i];
if (b[i] == d[m]) flag = 1;
}
sort(d + 1, d + m + 1), sort(vis + 1, vis + p + 1);
int p1 = 1, p2 = 1;
while (p1 <= p && p2 <= m) {
if (vis[p1] == d[p2]) p1++, p2++;
else p2++;
}
if (flag && p1 == p + 1) puts("YES");
else puts("NO");
}
return 0;
}
D. GCD-sequence
时间限制:2秒 空间限制:256MB 输入:标准输入 输出:标准输出
问题描述
两个整数 x 和 y 的最大公约数是能整除 x 和 y 的最大整数 z。例如,GCD(36,48) = 12,GCD(5,10) = 5,GCD(7,11) = 1。
Kristina 有一个数组 a,它恰好由 n 个正整数组成。她想计算每一对相邻数字的 GCD 以得到一个新的数组 b,称为 GCD 序列。
因此,GCD 序列 b 的元素将使用公式 计算,其中 \。
确定是否可以从数组 a 中恰好移除一个数字,使得 GCD 序列 b 是非递减的(即,始终满足 )。
例如,假设 Kristina 有一个数组 a = [20, 6, 12, 3, 48, 36]。如果她移除 ,并计算得到的GCD序列 \( b \),结果为:
得到的 GCD 序列 是非递减的,因为 。
输入格式
输入数据的第一行包含一个整数 t (),表示测试用例的数量。
接下来是每个测试用例的描述。
每个测试用例的第一行包含一个整数 n (),表示数组 a 中的元素数量。
每个测试用例的第二行包含恰好 n 个整数 (),表示数组 a 的元素。
保证所有测试用例中 n 的总和不超过 。
输出格式
对于每个测试用例,输出一行:
如果可以从数组 a 中恰好移除一个数字,使得 GCD 序列 b 是非递减的,则输出 "YES";
否则输出 "NO"。
答案可以以任何大小写形式输出(例如,字符串 "yEs", "yes", "Yes", 和 "YES" 都是正确答案)。
输入样例
输出样例
思路
从 b 数组递减的位置,分别删去对应的 a 数组的元素,再生成新的 GCD 序列,判断新序列是否不递减。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int t, n; vector<int> a(N);
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int gcd(int a, int b) { return a == 0 ? b : gcd(b % a, a); }
bool check(int x) {
if (x < 0 || x > n - 1) return false;
vector<int> c = a; vector<int> d;
c.erase(c.begin() + x);
for (int i = 0; i < n - 2; i++) {
d.push_back(gcd(c[i], c[i + 1]));
if (i && d[i] < d[i - 1]) return false;
}
return true;
}
void solve() {
n = read(); vector<int> b;
for (int i = 0; i < n; i++) a[i] = read();
for (int i = 0; i < n - 1; i++) b.push_back(gcd(a[i], a[i + 1]));
for (int i = 0; i < n - 2; i++) {
if (b[i] > b[i + 1]) {
if (check(i - 1) || check(i) || check(i + 1) || check(i + 2)) puts("YES");
else puts("NO");
return;
}
}
puts("YES");
}
int main() {
t = read();
while (t--) solve();
return 0;
}