Codeforces Round #748 (Div. 3) A B C D1

链接

A. Elections

题目大意

三个人的票数分别为a, b, c,求一个人票数离超过所有人还需要多少票

思路

分三种情况讨论:

  1. 最高票就一个人,则他只需再得到0票,其他人需要【最高票数 - 自身票数 + 1】 票
  2. 最高票有2个人,则这2个人都需要再得到1票(等同于【最高票数 - 自身票数 + 1】),剩下1个需要【最高票数 - 自身票数 + 1】 票
  3. 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;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值