最近好多人都参与了有道的比赛,其中第2题园子里有很多人给出了程序,在这里我也小谈一下我的想法。
题目要求:双倍超立方数是指一个正整数可以正好被拆分为两种不同的a^3+b^3的方式,其中a,b均为整数且0<a<=b。对于任何一个指定的 int n, 返回所有的小于等于n的双倍超立方数的个数。
Definition
Class: TwiceSuperCubic
Method: count
Parameters: int
Returns: int
Method signature: int count(int n)
(be sure your method is public)
Constraints
- n取值范围为1到1,000,000,000(含)
Examples
0)
1
Returns: 0
1)
1729
Returns: 1
1729=1^3+12^3
1729=9^3+10^3
2)
475574
Returns: 27
看了好多人的博客,都是源程序,猛地一看,还看得不怎么明白,自己也copy了一些成功人士的代码,试着做做改进,但在优化的过程中,猛地发现:我这是在搞算法吗?还是在搞程序?
什么是算法?看维基:http://zh.wikipedia.org/w/index.php?title=%E7%AE%97%E6%B3%95&variant=zh-cn
算法是指完成一个任务所需要的具体步骤和方法。也就是说给定初始状态或输入数据,能够得出所要求或期望的终止状态或输出数据。
算法常常含有重复的步骤和一些比较或逻辑判断。不同的算法可能用不同的时间、空间或效率来完成同样的任务。一个算法的优劣可以用空间复杂度与时间复杂度来衡量。
也就是算法是解决问题的办法,利用想出来的办法来解决现有的难题。
我们回头看一下题目,双超立方数,我没有搜到相关的定义,倒是维基里有1729和4104两个数的说明。这两个数都可以恰巧写成两个数立方和的形式,而且只有两种。
1729=1^3+12^3=9^3+10^3(这类数列的第一个)
4104=9^3+15^3=2^3+16^3
原题的意思即使找出小于n的能表示为上述形式的数字的数目。
看到题目好多人可能首先想起的是立方和公式:
a^3+3*a^2*b+3*a*b^2+b^3=(a+b)^3
对,化简之后就可以表达为:
a^3+b^3=(a+b)*(a^2-a*b+b^2)
首先我们应该能观察出双超立方数N应该不是素数,而且根据题目,应该恰好只有两对约数满足上面的式子,
即
a+b=A
a^2-a*b+b^2=B ‚
这是一个二元二次方程组,应该只有两组解。
我的思路是遍历小于n的自然数,然后找出只有四个约数的数字(除了1和自身),然后将这两组组解分别带入求得a和b。
将1式变成b=A-a带入到2式,得:
3*a^2-3*A*a+A^2-B=0
这是一个一元二次方程,有解的话,还记得吗?初中学 的,Δ >=0,今天解这个我费了老劲了,简单的带入变换老做错。
但是在这里我们知道,对于每一组给定的A和B,上面的方程应该有两个不同的整数解,
那就得Δ >0,下买你求Δ
Δ =(3*A)^2-4*3*(A^2-B)=4*B-A^2,要知道结果是整数解,所以4*B-A^2必能开平方。
所以两个解a,b是这是维基的图,只是借用其形式。
最后问题就变成了一个求不定方程组的问题,而且解都是自然数。
其中能归纳出一些数学约束关系出来,利用计算机程序确定范围求解。
我没有最后实现这个方法,只是想到了个也许能解决问题的方法,希望能给大家以帮助。
搞算法先将问题数学化,解决后再转化为程序。
后记:
相信很多人都听说过《计算机程序设计艺术》,比尔·盖茨在1995年说,“如果你认为你是一名真正优秀的程序员,就去读第一卷,确定可以解决其中所有的问题。”“如果你能读懂整套书的话,请给我发一份你的简历。”我至今没有敢动这部书,实在是不敢读。这糟老头子堪比霍金。