|
|
9#

楼主 |
发表于 2017-8-6 16:55:40
|
只看该作者
前面我们对边长从 0 开始逐个进行测试,速度很慢。从前面的输出的结果中发现,斜边边长 c(n) 满足如下规律:
- c(n+2) = 6 * c(n+1) - c(n)
复制代码
再根据初值 c(1)=1,c(2)=5,即可求得通项公式(求解过程略)。通项公式有两种等价的表示形式:
- c(n) = ( (2 - sqrt(2)) / 4 * (3 + sqrt(8))**n ) + ( (2 + sqrt(2)) / 4 * (3 - sqrt(8))**n )
复制代码
- c(n) = ( (sqrt(2)) / 4 * (sqrt(2) + 1)**(n+n-1) ) + ( (sqrt(2)) / 4 * (sqrt(2) - 1)**(n+n-1) )
复制代码
其中,双星号(**)表示乘方;“根号 8”其实就是 “2 倍的根号 2”;“n + n - 1”其实就是“ 2n - 1”。
有了通项公式,求解算法就优化了。下面的程序采用上述第一个通项公式。注意,通项公式中有两项(是相加的关系),被加数(第二项)总是小于 1,因此,暂时忽略不计。我们紧接着执行了一条 ((c++)),(注意 c 本身是整数,会自动进行取整),这样就弥补了刚才未加第二项所带来的损失。和前面的程序一样,我们用 2**0.5(即 2 的 0.5 次方) 来表示“根号2”,为的是尽量避免使用数学库函数 sqrt 。
- #!/bin/zsh
- integer a b c n;
- for (( n = 1; n < 15; n++))
- do
- c=$(((2 - (2**0.5))/4*((3+(8**0.5))**n)));
- ((c++));
- a=$((c/2**0.5));
- b=$((a + 1));
- if (( $a * $a + $b * $b == $c * $c ))
- then
- echo "$a, $b, $c";
- fi
- done
复制代码
运算结果如下:
- 0, 1, 1
- 3, 4, 5
- 20, 21, 29
- 119, 120, 169
- 696, 697, 985
- 4059, 4060, 5741
- 23660, 23661, 33461
- 137903, 137904, 195025
- 803760, 803761, 1136689
- 4684659, 4684660, 6625109
- 27304196, 27304197, 38613965
- 159140519, 159140520, 225058681
- 927538920, 927538921, 1311738121
- 5406093003, 5406093004, 7645370045
复制代码 |
|