51nod 1246 罐子和硬币

题目描述

有n个罐子,有k个硬币,每个罐子可以容纳任意数量的硬币。罐子是不透明的,你可以把这k个硬币任意分配到罐子里。然后罐子被打乱顺序,你从外表无法区别罐子。最后罐子被编上号1-n。每次你可以询问某个罐子,如果该罐子里有硬币,则你可以得到1个(但你不知道该罐子中还有多少硬币),如果该罐子是空的,你得不到任何硬币,但会消耗1次询问的机会。你最终要得到至少c枚硬币(c <= k),问题是给定n,k,c,由你来选择一种分配方式,使得在最坏情况下,询问的次数最少,求这个最少的次数。

数据范围1 <= n <= 10^9, 1 <= c <= k <= 10^9。

(一眼过去毫无思路,然而这只是个三级题啊??!!)
考虑最优的询问方案是什么?
每次将不确定是否有硬币的罐子都问一遍,确定了没有硬币的罐子就可以不管了
为什么这样最优呢?
一次询问,若确定了当前罐子没有硬币,就相当于浪费一次机会
我们的目的就是让浪费的机会的数量尽可能小
若一直问一个罐子直至它没有硬币,那肯定就肯定要浪费一次机会,而在最坏情况下,按这样的方案,每次先问到的罐子会是硬币最少的罐子,浪费的机会会被最大化
现在考虑最优分配方式
容易有一种猜想,平均分配
每次将不确定是否有硬币的罐子都问一遍
若平均分配,答案有两种可能
1,答案为c,这种情况出现于[k/n]*n>=c时,此时不会有浪费机会的情况
2,答案为c+n-(k%n),这种情况因为[k/n]*n < <script id="MathJax-Element-1" type="math/tex"><</script>c,所以最后一轮,有k%n个罐子是有1个硬币的,其余(n-(k%n))都没有硬币,最坏情况会先问到没有硬币的罐子,所以答案会增加n-(k%n)
然而平均分配不一定最优
平均分配在可能1中显然是最优的,而可能2并不一定
但给我们一个启发,最优分配方式,在经过几轮询问后,情况肯定是可能1
可能2中,我们肯定是要浪费一些机会,则要想办法尽可能多选罐子能留到可能1的局面,且这些罐子的硬币数是相等的,那显然答案就是c+n-留到可能1局面的罐子数
怎样尽可能多呢,那显然罐子的硬币数越少则越多嘛
这些罐子最少的硬币数显然为[k/n]+1
罐子的个数为n/([k/n]+1)
所以答案为c+n-n/([k/n]+1)
与平均分配得到的答案取更优值即为最终答案

代码

#include<cstdio>  
#include<string>  
#include<algorithm>  
using namespace std;  
int main()  
{   
    long long n,k,c;  
    scanf("%lld%lld%lld",&n,&k,&c);  
    long long num=k/n;     
    if(num*n>=c)  
    {  
       printf("%lld\n",c);  
       return 0;  
    }     
    long long ans=n-k%n+c;  
    int m=k/(num+1);
    if(ans>n-m+c)  
       ans=n-m+c;   
    printf("%lld\n",ans);  
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值