http://www.caiyiwen.tech/article/8.html
- H - Fishing Master
- 这道题当年打网络赛的时候是想了一个策略的,但是训练时忘了,所以重新从更加数学的角度思考了一下。
- 思路:我们总共需要n段钓鱼的时间和n段煮鱼的时间,其总和为nk+∑ti。然而我们有重合的部分需要减去,所以实际需要的时间为——nk+∑ti-重合部分。所以问题变成如何求出最大的重合部分,我们知道显然可以完全利用的时间只有煮鱼时间ti中k的整数倍,即ti%k的那一部分时间是注定会有损耗的。一开始没有鱼的时候必须花k的时间去钓一条鱼,所以如果∑(ti/k)≥n-1,总时间就直接是k+n*ti。
- 如果∑(ti/k)<n-1,那么我们还需要n-1-∑(ti/k)段时间去钓鱼,这些时间就是ti%k的那一部分,注定浪费时间。所以我们贪心地去ti%k最大的几个ti值即可减少浪费。
代码:
#include<cstdio>
#include<algorithm>
using namespace std;
int t[(int)1e5+10];
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
long long n,k;
scanf("%lld%lld",&n,&k);
long long cnt=0;
for(int i=0;i<n;++i)
{
scanf("%d",&t[i]);
cnt+=t[i]/k*k;
}
long long sum=0;
for(int i=0;i<n;++i)
{
sum+=t[i];
}
if(cnt>=(n-1)*k)
{
printf("%lld\n",k+sum);
}
else
{
for(int i=0;i<n;++i)
{
t[i]%=k;
}
sort(t,t+n,cmp);
int red=cnt/k;
for(int i=0;i<n-1-red;++i)
{
cnt+=t[i];
}
printf("%lld\n",n*k+sum-cnt);
}
}
return 0;
}