CodeForces - 1760F Quests
CodeForces - 1760F Quests
题解:二分答案
首先我们来分析一题目,如果说K越大,我们在d天里很有可能得不到C个硬币,所以K的最大值一定在合法答案和不合法答案的临界点,并且这些答案是单调的,所以我们直接考虑二分答案;
1.考虑不可能的情况:当K=0时,那么我们D天每天都去做获得硬币最多的工作,如果连这都满足不了C的条件,说明绝对答案不存在
2.考虑K趋于无穷大的情况:如果说K现在取无穷大,那就说明在D天里每个任务只能做一次,所以我们首先确定能做多少个任务,肯定是\(min(d,n)\),然后按照价值大到价值小的顺序做任务,得出sum,如果sum>=c,代表K可以取无穷大
3.其余情况直接二分答案,那么其实我们会发现一个规律,比如说d=5,k=5,a:4 2
天数1 2 3 4 5 4 2 0 0 4 我们会发现天数和数组a的小标会有一个这样的规律:\((i-1)mod(k+1)+1\)第i天取到的数组a元素下标
#include <bits/stdc++.h>
#define Zeoy std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0)
#define all(x) (x).begin(), (x).end()
#define endl '\n'
using namespace std;
typedef pair<int, int> pii;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-9;
const int N = 2e5 + 10;
ll n, c, d;
ll a[N];
bool check(int k)
{
ll sum = 0;
for (int i = 1; i <= d; ++i)
{
int x;
if ((i - 1) % (k + 1) + 1 > n) //如果超出数组a大小,x=0,没有贡献
x = 0;
else
x = a[(i - 1) % (k + 1) + 1];
sum += x;
}
if (sum >= c)
return 1;
else
return 0;
}
int main(void)
{
Zeoy;
int t = 1;
cin >> t;
while (t--)
{
cin >> n >> c >> d;
ll maxx = -1;
for (int i = 1; i <= n; ++i)
cin >> a[i];
sort(a + 1, a + n + 1, greater<ll>());
ll sum = 0;
ll pre = 0;
for (int i = 1; i <= d; ++i)
sum += a[1];
for (int i = 1; i <= min(n, d); ++i)
pre += a[i];
if (sum < c)
{
cout << "Impossible\n";
continue;
}
if (pre >= c)
{
cout << "Infinity\n";
continue;
}
int l = 0, r = d;
while (l <= r)
{
int mid = l + r >> 1;
if (check(mid))
{
l = mid + 1;
}
else
r = mid - 1;
}
cout << r << endl;
}
return 0;
}