1元钱买一瓶啤酒。
2个空瓶换一瓶啤酒。
问10元能买几瓶啤酒?
再问n元能买几瓶啤酒?
答:第一次:10瓶
第二次:10个空瓶换5个啤酒
第三次:5个空瓶换2个啤酒,剩一个空瓶
第四次:算上上次的空瓶,3个空瓶换1个啤酒,剩一个空瓶
第五次:算上第四次的一个空瓶,2个空瓶换1个啤酒,最后剩1个空瓶。结束。
合计:10+5+2+1+1=19
于是我推测公式:
第一次:10
第二次:10*1/2
第三次:10*1/(2^2)
第四次:10*1/(2^3)
第五次:10*1/(2^4),四舍五入为1(这步出错)
于是我归纳为10(1+1/2+1/2^2+...+1/2^n)
取极限为10(2-1/2^n)
公式中n=4,结果为19.375,取整为19。
问:当9元可买多少瓶?
9元可买9(2-1/2^n)
取n=4,结果为17.4375,取整17。

这个n的取法在于初始金额m<2^n,即可。我当时面试时取的时m>2^n时,n取最大值。
增加m<2^n这个条件后,公式m(2-1/2^n)=2m-m/2^n<2m-1.
所以,买啤酒问题实际的解是2m-1,即10元为19瓶,9元为17瓶。

考官的解为2m-1,用数学归纳法证明。这个证明未考虑详细。故不讨论。

 

 1  Console.WriteLine("买啤酒问题:一元买一瓶啤酒,两个空瓶换一瓶啤酒,问10元能买多少瓶啤酒?n元呢?请输入啤酒金额:");
 2 
 3           decimal money;
 4 
 5           while (!Decimal.TryParse(Console.ReadLine(), out money));
 6 
 7           int count = 0;//次数
 8 
 9           List<int> beerTotal = new List<int>();
10 
11           int full = (int)money;//啤酒
12 
13           beerTotal.Add(full);
14 
15           int empty = 0;//空瓶
16 
17           while (true)
18 
19           {
20 
21               //喝酒,出来空瓶了
22 
23               empty += full;
24 
25                 Console.WriteLine("第{0}次,买{1}瓶啤酒,有{2}瓶空瓶", count++, full, empty);
26 
27               //空瓶2换1啤酒
28 
29               full = empty / 2;
30 
31               //使用列表记录对话瓶数,最后统计
32 
33               beerTotal.Add(full);
34 
35               //剩余多少个啤酒
36 
37               empty = empty % 2;
38 
39               //当换不了啤酒就结束吧。
40 
41               if (full == 0)
42 
43                   break;
44 
45           }
46 
47             Console.WriteLine("{0}元可以买{1}瓶啤酒,哦顺便告诉你还剩{2}个空瓶", money, beerTotal.Sum(), empty);
48 
49           Console.ReadKey();
View Code