斐波那契数列的个位数出现的周期是多少?

24 阅读1分钟

背景

《斐波那契数列:定义自然法则的数学》 一书提到,斐波那契数列的个位数字会按照固定的周期重复出现。我们可以自己动手来探索这个周期的长度是多少。

正文

斐波那契数列

F1=1,F2=1F_1=1,F_2=1,对满足 n3n\ge 3nn 而言,Fn=Fn1+Fn2F_n=F_{n-1}+F_{n-2}。满足这样的规则的数列,我们称其为斐波那契数列。

基本的分析

为了方便讨论,我们记 an=(Fnmod10,Fn+1mod10)a_n=(F_n\bmod 10,F_{n+1}\bmod 10)。⬅️ 这里的小括号只是表示一对数字,没有特别的含义。 对比较小的 nnFn,Fnmod10,anF_n, F_n\bmod 10, a_n 的值列举如下

nnFnF_nFnmod10F_n\bmod 10ana_n
111111(1,1)(1,1)
221111(1,2)(1,2)
332222(2,3)(2,3)
443333(3,5)(3,5)
555555(5,8)(5,8)
668888(8,3)(8,3)
77131333(3,1)(3,1)
88212111(1,4)(1,4)
99343444(4,5)(4,5)
1010555555(5,9)(5,9)
1111898999(9,4)(9,4)
121214414444(4,3)(4,3)
131323323333(3,7)(3,7)
141437737777(7,0)(7,0)
151561061000(0,7)(0,7)
161698798777(7,7)(7,7)
17171597159777(7,4)(7,4)
18182584258444(4,1)(4,1)
19194181418111(1,5)(1,5)
20206765676555(5,6)(5,6)

生成上方表格的 Python3Python3 代码如下 ⬇️


print(r'| $n$ | $F_n$ | $F_n\bmod 10$| $a_n$ |')
print('| --- | --- | --- | --- |')

curr, next = 1, 1
for i in range(1, 21):
    print(f'| ${i}$ | ${curr}$ | ${curr%10}$ | $({curr%10},{next%10})$ |')
    curr, next = next, (curr + next)

对任意自然数 kk 来说,0(kmod10)90\le (k\bmod 10) \le 9 总是成立,所以 ana_n 的可能取值只有 10×10=10010\times10=100 个(有的值可能取不到)。根据鸽笼原理,a1,a2,,a101a_1,a_2,\cdots,a_{101}101101 个值必然有重复的(因为 ana_n 的可能取值只有 100100 个)。假设第一个重复出现的值为 adupa_{dup}adup=adupta_{dup}=a_{dup-t}。那么从 adupa_{dup} 开始,会有什么规律?

分析下标更大的项

注意到

an=(Fnmod10,Fn+1mod10)a_{n}=(F_{n}\bmod 10, F_{n+1} \bmod 10)
an+1=(Fn+1mod10,Fn+2mod10)a_{n+1}=(F_{n+1}\bmod 10, F_{n+2} \bmod 10)
Fn+2=Fn+1+FnF_{n+2}=F_{n+1}+F_n

所以

an+1=(Fn+1mod10,(Fn+1+Fn)mod10)a_{n+1}=(F_{n+1}\bmod 10, (F_{n+1} + F_n) \bmod 10)
=(an[1],(an[0]+an[1])mod10)=(a_n[1], (a_n[0]+a_n[1]) \bmod 10)

也就是说,从 ana_{n} 可以直接得出 an+1a_{n+1}。 既然 adup=adupta_{dup}=a_{dup-t},那么必然有 ⬇️

  • adup+1=adupt+1a_{dup+1}=a_{dup-t+1}
  • adup+2=adupt+2a_{dup+2}=a_{dup-t+2}
  • adup+3=adupt+3a_{dup+3}=a_{dup-t+3}
  • \cdots

所以一旦发现了第一个重复值 adupa_{dup},之后所有的值都会周期性出现(tt 是它的一个周期)。那么随之而来的问题就是 dupdup 具体是多少。

分析下标更小的项

刚才提到从 ana_{n} 可以直接得出 an+1a_{n+1},那么如果知道 an+1a_{n+1},能否反推出 ana_n 呢?我们试一试 ⬇️

an=(Fnmod10,Fn+1mod10)a_{n}=(F_{n}\bmod 10, F_{n+1} \bmod 10)
=((Fn+2Fn+1)mod10,Fn+1mod10)=((F_{n+2}-F_{n+1})\bmod 10,F_{n+1} \bmod 10)
=((an+1[1]an+1[0])mod10,an+1[0])=((a_{n+1}[1]-a_{n+1}[0])\bmod 10,a_{n+1}[0])

看来从 an+1a_{n+1} 也可以直接得出 ana_{n}

有趣的部分来了。考虑到 adup=adup+ta_{dup}=a_{dup+t},根据刚才提到的 “从 an+1a_{n+1} 也可以直接得出 ana_{n} 可知以下 dupdup 个等式都成立 ⬇️

  • adup=adup+ta_{dup}=a_{dup+t}
  • adup1=adup+t1a_{dup-1}=a_{dup+t-1}
  • adup2=adup+t2a_{dup-2}=a_{dup+t-2}
  • \cdots
  • a1=a1+ta_{1}=a_{1+t}

所以 a1+ta_{1+t} 会是第一个重复的值,它的值和 a1a_1 相等。如此说来,我们只要找到第一个和 a1a_1 相等的 ana_nn2n\ge2),就可以得出周期 t=n1t=n-1 了。

代码实战

我们可以将上述思路用 Python3Python3 来实现 ⬇️ (请将代码保存为 find_period.py


appeared_fib_pairs = set()
fib_pair = (1, 1)
n = 1
while True:
    if fib_pair in appeared_fib_pairs:
        break
    appeared_fib_pairs.add(fib_pair)
    print(f'{n}: {fib_pair}')
    next_fib_pair = (fib_pair[1], (fib_pair[0] + fib_pair[1]) % 10)
    fib_pair = next_fib_pair
    n += 1

用以下命令可以运行 find_period.py

python3 find_period.py

完整的运行结果如下

1: (1, 1)
2: (1, 2)
3: (2, 3)
4: (3, 5)
5: (5, 8)
6: (8, 3)
7: (3, 1)
8: (1, 4)
9: (4, 5)
10: (5, 9)
11: (9, 4)
12: (4, 3)
13: (3, 7)
14: (7, 0)
15: (0, 7)
16: (7, 7)
17: (7, 4)
18: (4, 1)
19: (1, 5)
20: (5, 6)
21: (6, 1)
22: (1, 7)
23: (7, 8)
24: (8, 5)
25: (5, 3)
26: (3, 8)
27: (8, 1)
28: (1, 9)
29: (9, 0)
30: (0, 9)
31: (9, 9)
32: (9, 8)
33: (8, 7)
34: (7, 5)
35: (5, 2)
36: (2, 7)
37: (7, 9)
38: (9, 6)
39: (6, 5)
40: (5, 1)
41: (1, 6)
42: (6, 7)
43: (7, 3)
44: (3, 0)
45: (0, 3)
46: (3, 3)
47: (3, 6)
48: (6, 9)
49: (9, 5)
50: (5, 4)
51: (4, 9)
52: (9, 3)
53: (3, 2)
54: (2, 5)
55: (5, 7)
56: (7, 2)
57: (2, 9)
58: (9, 1)
59: (1, 0)
60: (0, 1)

可见 ana_n 的周期是 6060,而 an[0]a_n[0] 就是斐波那契数列的个位数字,也就是说斐波那契数列的个位数字以 6060 为周期,循环出现。