题解:P13216 [GCJ 2015 #1A] Haircut
题目传送门。
思路
带着神秘时间限制的好奇心来到了此题。
一眼看认为是道贪心,后来怎么想怎么不对劲,知道看到
二分找什么呢?找出理
代码实现
check 函数如下:(
int check(int x)
{
int res=0;
for(int i=1;i<=n;i++) res+=x/a[i]+1;//+1 表示理发时间从 0 开始
return res;
}
二分代码如下:
int l=0,r=1e18,ans=-1;// 其实 r 不需要开那么大,纯属个人习惯
while(l<=r)
{
int mid=l+r>>1;
if(check(mid)>=k)
{
r=mid-1;
ans=mid;
}
else
{
l=mid+1;
}
}
完整代码:
#include<bits/stdc++.h>
#define int long long // 一定要开 long long !
using namespace std;
int t,n,k;
int a[1010];
vector<int> e;
int check(int x)
{
int res=0;
for(int i=1;i<=n;i++) res+=x/a[i]+1;
return res;
}
signed main()
{
cin>>t;
for(int Case=1;Case<=t;Case++)
{
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
int l=0,r=1e18,ans=-1;
while(l<=r)
{
int mid=l+r>>1;
if(check(mid)>=k)
{
r=mid-1;
ans=mid;
}
else
{
l=mid+1;
}
}
int pos=k-check(ans-1)-1; //记得 -1 ,时间从 0 开始
e.clear();
for(int i=1;i<=n;i++)
if(!(ans%a[i])) //表示恰巧在 ans-1 时刻理完顾客发的理发师可以给你理发
e.push_back(i);
cout<<"Case #"<<Case<<": "<<e[pos]<<'\n';
}
return 0;
}