【题目】
1000个苹果放入10个箱子。客户如果要获得1~1000个苹果中的任意个数,都可以整箱搬,而不用拆开箱子。问是否有这样的装箱方法?
【问题背景】
这是从《对话》节目中 李开复 博士现场面试清 华 博士生时提到的一个问题。题目结构及意思比较简单明确,可求解过程似乎并不那么容易。虽然节目中有提示,但直到节目看完,还是一头雾水。下面给出我自己的想法及解题思路,希望与有兴趣的朋友一起讨论。
【答案】
节目现场给出了一些提示,并没有公布正确答案,按照节目中的提示,应该存在这样的装箱方法,结果是:
1,2,4,8,16,32,64,128,256,489
【数值试验】
先对9~17做数值试验。
9:1+8 10:2+8 11:1+2+8
12:4+8 13:1+4+8 14:2+4+8
15:1+2+4+8 16:16 17:16+1
【程序穷举】
//定义结果
private static int[] vars = {1, 2, 4, 8, 16, 32, 64, 128, 256, 489};
//记录不重复使用标识
private static boolean[] has = new Boolean[vars.length];
//任给value检验是否可以按结果拆分
private static boolean isSum(int value) {
boolean result = false;
int len = vars.length;
for (int i = 0; i < len; i++) {
has[i] = true;
}
for (int i = len - 1; i >= 0; i--) {
if (value >= vars[i] && has[i]) {
value -= vars[i];
has[i] = false;
if (value == 0)
return true;
}
}
return false;
}
//主函数调试
public static void main(String[] args) {
for (int i = 1; i <= 1000; i++)
System.out.println(i+” ”+ isSum(i));
}
【论证思路】
(正向思路)任给小于1000的整数可以表示成以2为公比的等比数列{2**n}中某些个数的集合,且集合中没有重复数值。
(反向思路)
[1]以2为公比的等比数列{2**n}任意提取k个值求和结果不同;
[2]以2为公比的等比数列{2**n}任意提取k个值所有求和可以获得2**(n+1)-1个结果。
【证明过程】
下面以反向思路证明。
已知以2为公比的等比数列:1,2,4,8,16,...
首先将前n项相加,得到和为:2**n-1
第n项与第1项相加得到和为:2**(n-1)+1
因此任取k个数相加的和属于(2**(n-1),2**n),且和不重复。
至此证明了[1]。
数列前n项任取k个求和构成的和的总个数为
S = C(n,1)+C(n,2)+C(n,3)+...+C(n,k)+...+C(n,n)
泰勒级数展开式为
f=f0+f1*x**1/(1!)+f2*x**2/(2!)+...+fn*x**n/(n!)+...
构造函数f=x**n
采用泰勒级数在x=1处展开,其中f在x=1处的n阶导数为:
f0=x**n=1
f1=nx**(n-1)=n
f2=n(n-1)x**(n-2)=n(n-1)
fn=n!x**0=n!
f(n+1)=0
令y=x-1由此
f=x**n=1+n*y+n(n-1)*y**2/2!+...+n!*y**n/n!
=1+C(n,1)y+C(n,2)*y**2+...+C(n,k)y**k+...+C(n,n)*y**n
当x=2时
2**n=1+C(n,1)+C(n,2)+...+C(n,k)+...+C(n,n)=S+1
因此
S=2**n-1
即前n项数列任取k个求和构成的和的个数为2**n-1
至此证明了[2]。
而数列第n+1项为2**n
至此命题得证。
【扩展】
因为1000<1024,应该有其它方法。
刚查了一下,找到了另一种解法:{500,250,125,63,31,16,8,4,2,1}
但是对于等比数列似乎只有以2为公比的等比数列才满足要求。
是否还有其它的论证过程呢?节目中李开复一直说二进制,是否可以用二进制计数法证明?
【结论】
证明过程是否严谨,还有待考究。
但是可以肯定结果{1,2,4,8,16,32,64,128,256,489}是满足要求的,通过测试程序的输出结果说明了这点。