专栏文章
题解:P13216 [GCJ 2015 #1A] Haircut
P13216题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mioddpf7
- 此快照首次捕获于
- 2025/12/02 17:22 3 个月前
- 此快照最后确认于
- 2025/12/02 17:22 3 个月前
思路
带着神秘时间限制的好奇心来到了此题。
一眼看认为是道贪心,后来怎么想怎么不对劲,知道看到 才恍然大悟: 以上过不去呀,只能使用 的算法:二分!
二分找什么呢?找出理 个人发的最短时间,设其为 分钟。而为你理发的理发师编号是多少关键就在于第 分钟理完了多少顾客,设其为 名,然后,第 名顾客对号入座,而你是最后选择的那个人,第 名顾客中一共有 名顾客,你就自然对应了第 名理发师。
代码实现
check 函数如下:( 表示理 个人发的最短时间)
CPPint check(int x)
{
int res=0;
for(int i=1;i<=n;i++) res+=x/a[i]+1;//+1 表示理发时间从 0 开始
return res;
}
二分代码如下:
CPPint 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;
}
}
完整代码:
CPP#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;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...