好久没来英雄会了,所以今天来看看几题,看到“罐子与硬币”这一题不错,这种题目比较适合我的味道,不过,可惜啊...性子太急,分没到手...
题目如下:
有n个罐子,有k个硬币,每个罐子可以容纳任意数量的硬币。罐子是不透明的,起初你可以随机把这k个硬币任意放在罐子里。然后罐子被打乱顺序,你从外表无法区别罐子。最后罐子被编上号1-n。你有p次机会,每次你可以选择某个罐子,如果该罐子里有硬币,则你可以得到1个(你不可以知道该罐子里有多少硬币),如果该罐子是空的,你得不到任何硬币。
你最终要得到至少c枚硬币,我们的问题是给定n,k,c,求出最少的p,存在一种你最初放硬币的方式,无论罐子如何被打乱顺序,你都能p次机会内获得至少c个硬币。
输入n,k,c (0 < n <=1000000, 0 < c <= k <=1000000)。
输出,最小的p值。 例如n = 3, k = 6, c = 4。 你可以把每个罐子放入两个硬币,这样得到4次机会可以得到4个硬币,输出4。
题目的要求是:无论罐子如何被打乱顺序,都能p次机会内获得至少c个硬币。我们可以这样理解,只要存在空的,我们肯定会选中;
错误1:将k个硬币先均匀分到n个罐子中,多余的部分则每一个分到罐子中;
这样提交:
if(k < c)
return 0;
int num = k / n; //每个罐子可以放的硬币
int count = k % n; //多出的硬币
if(num * n >= c)
return c;
else
{
int count1 = n - count; //此时的空瓶
int p = count1 + c;
return p;
}
测试点n = 3, k = 6, c = 4倒是过了,可是提交上去,说测试点n = 3, k = 4,c = 4没过;
运行了一下,我的结果是6;
可是一想,如第一个罐子为空,第二个,第三个罐子放两个;
这样我们首先抽到第一个罐子,后面四次分别为第二个、第三个、第二个、第三个,只需五次即可;
错误2:所以这样理解,将k个硬币真正均分至i个罐子中,n - i个罐子为空,如下:
if(k < c)
return 0;
int num = k / n; //每个罐子可以放的硬币
if(num * n >= c)
return c;
else
{
for(int i = n; i > 0; i--)
{
if(k % i == 0)
{
return c + n - i;
}
}
}
可是这样的结果依然没过,测试点n = 1000, k = 12345, c = 12340,我的结果是12517。
这次的数据有点大,我也画不出来啊...
终结:这时候想到早上转的篇文章,当你学不进去的时候,试试“普瑞馬”法则中的“大脑集中精力最多只有25分钟。这是对成人而言,所以学习20到30分钟后就应该休息10分钟。你可以利用这段时间做点家务,10分钟后再回来继续学习,效果会更好。”正巧到饭点的时间,就去吃了个饭,回来突发奇想:
我们可以有n1个罐子是空的,n2个罐子是装k1个硬币的(n2为1或0),n3个罐子是装k2个硬币的。
n1 + n2 + n3 = n;
n1 * 0 + n2 * k1 + n3 * k2 = k;
其中包括的上面的第二种情况,即n2 = 0时,有n1 + n2个罐子为空,n3个罐子是k2个硬币,当然k1 < k2,否则我们寻找硬币到后来连n3个空罐子都得加上了...;
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
class Test {
public:
static int pvalue (int n,int k,int c)
{
if(k < c)
return 0;
int num = k / n; //每个罐子可以放的硬币
int max = 100000000;
if(num * n >= c)
return c;
else
{
for(int i = n - 1; i > 0; i--)
{
num = k / i; //装i个整罐子,每个装num
int num1 = k - num * i; //多的一个罐子装num1个
int p;
if(num1 == 0) //
{
p = n - i + c;
}
else
{
if(c <= num1 * (i + 1) && num > num1)
{
p = n - i - 1 + c;
}
else if(num > num1)
p = n - i - 1 + c + 1;
else
p = c + n - 1;
}
if(max > p)
max = p;
}
}
return max;
}
};
//start 提示:自动阅卷起始唯一标识,请勿删除或增加。
int main()
{
cout<<Test::pvalue(3,4,4)<<endl;
}
//end //提示:自动阅卷结束唯一标识,请勿删除或增加。
(*∩_∩*)