F. Quests(二分)

Problem - F - Codeforces

 

有n个任务。如果你完成第i个任务,你将获得ai币。你每天最多只能完成一个任务。然而,一旦你完成了一个任务,在K天内你不能再做同样的任务。(例如,如果k=2,你在第1天做了任务1,那么你在第2天或第3天不能做,但你可以在第4天再做)。

给你两个整数c和d。找出k的最大值,使你在d天内至少能获得c个硬币。如果不存在这样的k,则输出Impossible。如果k可以是任意大的,则输出Infinity。

输入
输入由多个测试案例组成。第一行包含一个整数t(1≤t≤104)--测试案例的数量。测试用例的描述如下。

每个测试用例的第一行包含三个整数n,c,d(2≤n≤2⋅105;1≤c≤1016;1≤d≤2⋅105)--任务的数量,你需要的硬币数量,以及天数。

每个测试案例的第二行包含n个整数a1,a2,...,an(1≤ai≤109)--任务的奖励。

所有测试案例的n之和不超过2⋅105,所有测试案例的d之和不超过2⋅105。

输出
对于每个测试用例,输出以下结果之一。

如果不存在这样的k,输出Impossible。
如果k可以是任意大的,则输出Infinity。
否则,输出一个整数--k的最大值,使你在d天内至少能获得c个硬币。
请注意,检查器是区分大小写的,你应该完全按照给出的字符串来输出。
例子
inputCopy
6
2 5 4
1 2
2 20 10
100 10
3 100 3
7 2 6
4 20 3
4 5 6 7
4 100000000000 2022
8217734 927368 26389746 627896974
2 20 4
5 1
输出拷贝
2
杅眕
不可能的
1
12
0
备注
在第一个测试案例中,在k=2的情况下,在4天内赚取5个金币的方法如下。

第1天:做任务2,赚取2个金币。
第二天:做任务1,赚取1个金币。
第三天:什么都不做。
第四天:做任务2,赚取2个硬币。
总的来说,我们赚了2+1+2=5个硬币。
在第二个测试案例中,我们可以通过做第一个任务赚取100个硬币,在第一天本身就可以赚取超过20个硬币,所以k的值可以任意大,因为我们从来不需要做另一个任务。

在第三个测试案例中,无论我们怎么做,我们都无法在3天内赚到100个硬币。

题解:
首先我们把无限,与不可能的情况去除,

什么时候无限,就是,min(d,n)个前最大的相加>=c,不需要重复加最大的都可完成,

不可能则是每天都是最大的*d都无法达到c,就是不可能

然后就是二分k的最大值,因为根据k的大小,钱数的大小肯定也是单调的

关键是check函数怎么写,

这里看了一下大佬的,觉得写的很简洁,很不错

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define int long long
int a[200050];
void solve()
{

	long long n,c,d;
	cin >> n >> c>>d;
	for(int i = 1;i <= n;i++)
	{
		cin >> a[i];
	}
	sort(a+1,a+1+n,greater<int>());
	long long s = 0;
	for(int i = 1;i <= min(n,d);i++)
	s+= a[i];
	if(s >= c)
	{
		cout<<"Infinity\n";
		return ;
	} 
	if(a[1]*d < c)
	{
		cout<<"Impossible\n";

		return ;
	}
	int l = 0,r = 2e5;
	while(l < r)
	{
		int mid = (l + r+1)/2;
		s = 0;
		for(int i = 1;i <= d;i++)
		{
			int id = ((i-1) % (mid+1)+1);
			if(id <= n)
			{
				s += a[id];
			}

		}
		if(s >= c)
		{
			l = mid;
		}
		else
		{
			r = mid-1;
		}

	}
	cout<<l<<"\n";

}
signed main()
{
	int t = 1;
	cin >> t;
	while(t--)
	{
		solve();
	}
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值