A. Equality
因为是子序列,所以只要判断前 k k k 个字母最多组成多少个子序列就行了
#include <iostream>
#include <climits>
#include <algorithm>
const int MAXN = 1e5 + 2;
std::string str;
int n, k, ans = INT_MAX;
int cnt[MAXN];
int main()
{
std::ios_base::sync_with_stdio(0);
std::cin >> n >> k >> str;
for (int i = 0; i < n; i++) {
cnt[str[i] - 'A']++;
}
for (int i = 0; i < k; i++) {
ans = std::min(ans, cnt[i]);
}
std::cout << ans * k << std::endl;
return 0;
}
B. Non-Coprime Partition
根据求和公式,前 n − 1 n-1 n−1 项和为 ( n − 1 ) n 2 \frac{(n-1)n}{2} 2(n−1)n ,而最后一项正是 n n n ,两者的 g c d gcd gcd 就是 n n n ,然后再特判一下 n = 1 n=1 n=1 和 n = 2 n=2 n=2 的情况就行了
#include <bits/stdc++.h>
using namespace std;
int n;
int main()
{
scanf("%d", &n);
if (n == 1) puts("No");
else if (n == 2) puts("No");
else {
puts("Yes");
printf("%d ", n - 1);
for (int i = 1; i < n; i++) {
printf("%d ", i);
}
printf("\n1 %d\n", n);
}
return 0;
}
C. Gambling
根据题意, A A A 和 B B B 每次都要移除对手的一个数字或者拿走自己的一个数字,容易发现 A A A 和 B B B 每次都将移除或拿走当前最大的数字,所以直接模拟即可
#include <cstdio>
#include <algorithm>
const int MAXN = 100000 + 5;
int n;
long long ans;
int a[MAXN], b[MAXN];
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i <= n; i++) scanf("%d", &b[i]);
std::sort(a + 1, a + 1 + n);
std::sort(b + 1, b + 1 + n);
int na = n, nb = n;
char turn = 'a';
while (na > 0 && nb > 0) {
if (turn == 'a') {
if (a[na] > b[nb]) {
ans += a[na];
na--;
}
else nb--;
turn = 'b';
}
else {
if (b[nb] > a[na]) {
ans -= b[nb];
nb--;
}
else na--;
turn = 'a';
}
}
if (na > 0) {
if (turn == 'a') {
for (int i = na; i >= 1; i -= 2) {
ans += a[i];
}
}
else {
for (int i = na - 1; i >= 1; i -= 2) {
ans += a[i];
}
}
}
if (nb > 0) {
if (turn == 'a') {
for (int i = nb - 1; i >= 1; i -= 2) {
ans -= b[i];
}
}
else {
for (int i = nb; i >= 1; i -= 2) {
ans -= b[i];
}
}
}
printf("%lld\n", ans);
return 0;
}
D. Slime
设全部数字绝对值之和为
s
u
m
sum
sum。
当全部都是正数的时候,让一个数
a
a
a 不断减去他旁边的数到只剩
2
2
2 个数字,然后再用剩的那个数字
b
b
b 减去
a
a
a ,这样每个数相当于都加到了
b
b
b 中,唯独
a
a
a 不但没加还减去了,所以最后答案为
s
u
m
−
2
a
sum-2a
sum−2a 。
当全部都是负数的时候和上面同理,最后答案为
s
u
m
−
∣
2
a
∣
sum-|2a|
sum−∣2a∣
当有正有负的时候让负数减去旁边的正数直到只剩一个正数,然后那个正数再减掉所有的负数就好,所以答案为
s
u
m
sum
sum。
所以要让答案最大就是让
∣
2
a
∣
|2a|
∣2a∣ 最小。
#include <cstdio>
#include <algorithm>
#include <climits>
int n, max = INT_MIN, min = INT_MAX;
long long ans;
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int tmp;
scanf("%d", &tmp);
max = std::max(max, tmp);
min = std::min(min, tmp);
ans += abs(tmp);
}
if (n == 1) {
printf("%d\n", max);
return 0;
}
else if (n == 2) {
printf("%d\n", abs(max - min));
return 0;
}
if (max < 0) {
printf("%lld\n", ans - 2 * abs(max));
}
else if (min > 0) {
printf("%lld\n", ans - 2 * abs(min));
}
else printf("%lld", ans);
return 0;
}