Let’s fix k k k and find the maximum number of coins we can get. Here we can do a greedy solution: at every step, we should always take the most rewarding quest. (Intuitively, it makes sense, since doing more rewarding quests earlier allows us to do them again later.) If no quests are available, we do nothing.
To implement this, sort the quests in decreasing order, and 0 0 0-index them. On day i i i we should do quest i i i m o d mod mod k k k, provided that this value is less than n n n. This is because after every k k k days, we cycle back to the first quest. Thus we solved the problem for a fixed k k k in O ( d ) O(d) O(d) with O ( n l o g n ) O(nlogn) O(nlogn) precomputation to sort the array.
Now to solve the problem, we can binary search on the answer, since if some k k k works, then all smaller k k k work. The minimum value of k k k is 0 0 0, and the maximum value is n (for larger k k k, we won’t be able to do the same quest multiple times anyways, so it’s useless to consider them).
If we find that k k k always goes towards the smaller end of our binary search and k = 0 k=0 k=0 still fails, we output I m p o s s i b l e Impossible Impossible. If we find that k k k always goes towards the larger end of our binary search and k = n k=n k=n still fails, we output I n f i n i t y Infinity Infinity. Otherwise, just output k k k.
The overall time complexity is O ( n l o g n + d l o g n ) O(nlogn+dlogn) O(nlogn+dlogn).
Remark. It is not hard to improve the solution to O ( n l o g n ) O(nlogn) O(nlogn). Originally, I proposed the problem this way, but we ended up removing this part of the problem because the implementation of this solution was tricky enough.
#include
using namespace std;
typedef long long LL;
const int N = 200010;
LL a[N];
int main()
{
int T=1;cin>>T;
while(T--)
{
LL n,c,d;cin>>n>>c>>d;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
reverse(a+1,a+n+1);
for(int i=2;i<=n;i++) a[i]+=a[i-1];
if(a[1]*d<c)
{
cout<<"Impossible"<<endl;
continue ;
}
if(a[min(n,d)]>=c)
{
cout<<"Infinity"<<endl;
continue ;
}
auto check=[&](int mid){
LL sum=0;
LL dd=d/mid;
LL yy=d%mid;
if(mid>=n) sum+=dd*a[n];
else sum+=dd*a[mid];
if(yy>=n) sum+=a[n];
else sum+=a[yy];
if(sum<c) return false;
else return true;
};
int l=1,r=200000;
while(l<r)
{
int mid=(l+r+1)>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
cout<<l-1<<endl;
}
return 0;
}