CF1223C 贪心+二分

文章描述了一个编程竞赛的问题,要求找出最小的票数n,使得卖出n张票并按照特定规则捐赠后,至少获得k金额。策略涉及贪心思想和二分搜索,代码中实现了将票按价格降序排列,然后计算不同位置的捐赠,通过二分查找确定最小票数。
摘要由CSDN通过智能技术生成

CF1223C Save the Nature

题意:

有n张票需要卖出,你可以选择任意数字,做任意序列。

  • 第i张能被a整除会拿出x%来捐赠。
  • 第i张能被b整除会拿出y%来捐赠。
  • 如果这张票的位置能同时被a和b整除则拿出(x+y)%来捐赠。
  • 给出票价均是100的倍数,不需要任何舍入。

现在需要找到用最小的门票数量n来至少赚取k数量的钱

思路:

因为票的位置可以随意排列,可以选择利用贪心策略来找到用更少的门票数量来赚取更多的钱,但我们不知道如何找到如何使用最小的门票数量来至少赚取k数量的钱,所以需要对每次贪心后得到的钱进行遍历找到最小门票数量,为了降低时间复杂度,因为门票价格是有序的,所以可以使用二分查找。最终时间复杂度是排序+二分的时间复杂度O(nlog2n)

代码:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
#include <functional>
#include <set>
#define int long long
#define MAXN 200010
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
using namespace std;
int arr[MAXN];
int arr2[MAXN];

signed main() {
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int n;
	int t;
	cin >> t;
	while (t--) {
		int x, y, a, b, k;
		int ans = -1;
		cin >> n;
		for (int i = 1; i <= n; ++i) {
			cin >> arr[i];
			arr[i] /= 100;//因为题目给出票价是100的倍数,所以这里直接处理
		}
		cin >> x >> a;
		cin >> y >> b;
		cin >> k;
		auto search = [=](int n) {//查找票价最高是多少
			int sum = 0;
			for (int i = 1; i <= n; ++i) {
				arr2[i] = 0;
				if (i % a == 0) {
					arr2[i] += x;
				}
				if (i % b == 0) {
					arr2[i] += y;
				}
			}
			sort(arr2 + 1, arr2 + 1 + n, greater<int>());//从大到小排序
			for (int i = 1; i <= n; ++i) {
				sum += arr[i] * arr2[i];
			}
			return sum >= k;
		};
		sort(arr + 1, arr + 1 + n, greater<int>());
		int l=1, r=n;
		while (l<=r) {
			int mid = (l + r) / 2;
			if (search(mid)==true) {
				ans = mid;
				r = mid - 1;
			}
			else {
				l = mid + 1;
			}
		}
		cout << ans << endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值