A. Elections
题目大意
三个人的票数分别为a, b, c,求一个人票数离超过所有人还需要多少票
思路
分三种情况讨论:
- 最高票就一个人,则他只需再得到0票,其他人需要【最高票数 - 自身票数 + 1】 票
- 最高票有2个人,则这2个人都需要再得到1票(等同于【最高票数 - 自身票数 + 1】),剩下1个需要【最高票数 - 自身票数 + 1】 票
- 3个人票数相同,每个人都需要再得到1票(等同于【最高票数 - 自身票数 + 1】)
不难发现,只有在最高票只有一个人的情况下,得票最高的人需要0票,其他情况下每个人都需要【最高票数 - 自身票数 + 1】 票
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <cmath>
typedef long long ll;
using namespace std;
#define ioClose
#define endl '\n'
#define Ttest
const int maxn = 1e5 + 5;
const int mod = 998244353;
void solve() {
int a, b, c;
cin >> a >> b >> c;
// 最高票的票数
int maxNum = max(max(a, b), c);
// 最高票的人数
int count = 0;
if (a == maxNum)
count++;
if (b == maxNum)
count++;
if (c == maxNum)
count++;
// 只有在最高票只有一个人的情况下,得票最高的人需要0票,其他情况下每个人都需要【最高票数 - 自身票数 + 1】 票
if (count == 1)
cout << (a == maxNum ? 0 : maxNum - a + 1) << " " << (b == maxNum ? 0 : maxNum - b + 1) << " " << (c == maxNum ? 0 : maxNum - c + 1) << endl;
else
cout << maxNum - a + 1 << " " << maxNum - b + 1 << " " << maxNum - c + 1 << endl;
}
int main() {
#ifdef ioClose
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#endif
#ifdef Ttest
int T;
cin >> T;
while (T--) {
#endif
solve();
#ifdef Ttest
}
#endif
return 0;
}
B. Make it Divisible by 25
题目大意
给你一个数字,你可以删除任意位置上的数字,让你求最小的删除操作次数使该数字能被25整除
思路
观察到25的倍数的后2位数是 [00, 25, 50, 75],因此采用贪心的原则,求得到这些后缀的最小操作数分别是多少(即要删除的元素个数为多少),再取其中操作次数最少的次数即为答案
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <cmath>
#include <sstream>
typedef long long ll;
using namespace std;
#define ioClose
#define endl '\n'
#define Ttest
const int maxn = 1e9 + 5;
const int mod = 998244353;
string s;
int len;
// 求使后缀变成 ba 的最小操作数
int fun(char b, char a) {
// 记录当前操作到的下标
int i = len - 1;
// flag1 记录从后往前找到第一个 a 的下标,flag2 记录从后往前找到第一个 b 的下标
int flag1 = -1, flag2 = -1;
// 从后往前遍历查找 a 的下标,找到或者超出数组下标范围退出循环
while (flag1 == -1 && i >= 0) {
if (s[i] == a) flag1 = i;
i--;
}
while (flag2 == -1 && i >= 0) {
if (s[i] == b) flag2 = i;
i--;
}
// 如果能找到返回要删除的元素个数,即最少操作数
if (flag2 != -1) return(len - flag2 - 2);
// 不能找到则返回一个极大值
return maxn;
}
void solve() {
// 输入为字符串便于操作
cin >> s;
// 字符串的长度
len = s.length();
// 结果先赋一个极大值
int ans = maxn;
// 取到4种后缀的最小操作数
ans = min(ans, fun('0', '0'));
ans = min(ans, fun('2', '5'));
ans = min(ans, fun('5', '0'));
ans = min(ans, fun('7', '5'));
cout << ans << endl;
}
int main() {
#ifdef ioClose
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#endif
#ifdef Ttest
int T;
cin >> T;
while (T--) {
#endif
solve();
#ifdef Ttest
}
#endif
return 0;
}
C. Save More Mice
题目大意
在坐标轴上,猫在0点,洞在n点,老鼠在 (0, n) 之间的点,多个老鼠可以站在同一点,老鼠跑到洞里猫就不能吃它,你可以选择移动一只老鼠一步,之后猫也会向前移动一步,问你能拯救老鼠的最大数量
思路
猫到达洞口的时间是一定的,我们在有限的时间内想多拯救老鼠,就一定要救拯救所花费时间短的老鼠
离洞口近的老鼠我们一定会救,因为救它花费的时间最短(这里不是指先救离洞口最近的老鼠),因此我们先记录猫到达洞口之前我们可以用的时间 temp,然后逐个将离洞口近的老鼠救出(这个先不是指时间),接着 temp 减去救这只老鼠的时间,循环即可得到答案
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <cmath>
typedef long long ll;
using namespace std;
#define ioClose
#define endl '\n'
#define Ttest
const int maxn = 4e5 + 5;
const int mod = 998244353;
// 记录老鼠离洞口的距离
ll a[maxn];
void solve() {
ll n, k;
cin >> n >> k;
for (ll i = 0; i < k; i++) {
cin >> a[i];
a[i] = n - a[i];
}
// 排序,先救离洞口近的老鼠(“先”不指时间)
sort(a, a + k);
// ans 记录最多可以救的老鼠数量,i 记录老鼠的下标,temp 记录可用的时间
ll ans = 0, i = 0, temp = n;
while (1) {
if (i >= k)
break;
// temp 不能等于 a[i],等于代表猫和老鼠是在同一点
if (temp > a[i]) {
// 救出老鼠后时间减少
temp -= a[i];
i++;
ans++;
} else break;
}
cout << ans << endl;
}
int main() {
#ifdef ioClose
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#endif
#ifdef Ttest
int T;
cin >> T;
while (T--) {
#endif
solve();
#ifdef Ttest
}
#endif
return 0;
}
D1. All are Same
题目大意
有 n 个数,你可以选择一个数 k(k>= 1),然后让 n 个数减去 k 后值相等(次数不限),求 k 所能取的最大值
思路
数据较小,先记录 n 个数距其中最小的数的差值,暴力枚举除0外的差值,求他们的最大公因数即可
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <cmath>
#include <set>
#include <vector>
typedef long long ll;
using namespace std;
#define ioClose
#define endl '\n'
#define Ttest
const int maxn = 1e5 + 5;
const int mod = 998244353;
int a[maxn];
void solve() {
int n;
cin >> n;
// 记录 n 个数之中最小的数值
ll minn = 1e7;
set<ll> st;
for (int i = 0; i < n; i++) {
cin >> a[i];
if (a[i] < minn) minn = a[i];
st.insert(a[i]);
}
// 记录除等于最小数值外的其他每个数与最小数值的差值
vector<ll> v;
for (auto it : st) {
// 去掉最小数值的差值(0)
if (it == minn) continue;
v.push_back(it - minn);
}
// 如果 n 个数全相等的话 k 可以取任意大小
if (v.size() == 0) {
cout << -1 << endl;
return;
}
// 从后往前遍历差值
for (int j = v[0]; j >= 2; j--) {
bool flag = false;
for (int i = 0; i < v.size(); i++) {
if (v[i] % j != 0) {
flag = true;
break;
}
}
// 如果找到了最大公因数就输出
if (!flag) {
cout << j << endl;
return;
}
}
cout << 1 << endl;
}
int main() {
#ifdef ioClose
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#endif
#ifdef Ttest
int T;
cin >> T;
while (T--) {
#endif
solve();
#ifdef Ttest
}
#endif
return 0;
}