冪的一個公式(二)

黃志斌發表於2017-02-19

斐波那契數列定義如下:

  • Fn = Fn-1 + Fn-2,       F1 = F2 = 1

,可以使用以下 Haskell 程式來計算 g(105):

import Math.NumberTheory.Powers ( powerMod )
m = 9; m1 = 10^m; m2 = 4*5^(m-1)
p2 n = powerMod 2 n m1
fibs = map fst $ iterate (\(a,b)->(b,a+b)) (1,1) :: [Integer]
main = print $ mod (sum $ map p2 $ take (10^5) fibs) m1

這個程式的執行時間是 6 分 59 秒。

如果把上述 Haskell 程式中的 p2 函式替換為:

p2 n = powerMod 2 (if n < m2 then n else mod (n-m) m2 + m) m1

這個程式的執行時間是 1.47 秒。

如果 p2 函式替換為:

p2 n = powerMod 2 (mod n m1) m1

這個程式的執行時間是 1.39 秒,它在 99.999999% 的情況下能夠給出正確答案。


以下 3 個公式,前 2 個是正確的,第 3 個不正確。

  • (a ± b) mod m = (a mod m ± b mod m) mod m
  • ab mod m = (a mod m) (b mod m) mod m
  • 2n mod m = 2 n mod m mod m

如果 m = 109,第 3 個公式出錯的概率小於一億分之一。


以下 C 語言程式的執行時間是 0.014 秒:

#include <stdio.h>

int powerMod(int a, int b, int m)
{
  long v = 1;
  for (; b; b >>= 1, a = (long)a * a % m) if (b & 1) v = v * a % m;
  return (int)v;
}

int main(void)
{
  int m = 9, m1 = (int)1e9, m2 = 1562500, n = (int)1e6, z = 0;
  for (int i = 0, f1 = 1, f2 = 1, f3; i < n; i++, f1 = f2, f2 = f3) {
    f3 = (f1 + f2) % m2;
    if (i > 5 && f1 < m) f1 += m2;
    z = (powerMod(2, f1, m1) + z) % m1;
  }
  printf("%d\n", z);
}

如果刪除 main 函式 for 迴圈中的 if 語句,這個程式也幾乎是正確的。


  • g(101) = 200938800
  • g(102) = 075829040
  • g(103) = 195598640
  • g(104) = 273294640
  • g(105) = 050254640
  • g(106) = 819854640
  • g(107) = 515854640
  • g(108) = 475854640
  • g(109) = 075854640

我們有以下猜想:

  • 猜想1:當 n ≥ 1 時,g(10n) 是 10 的倍數。
  • 猜想2:當 n ≥ 9 時,g(10n) = 75854640。

經計算,得到:g(1011) = g(1010) = g(109)。


數列 Fn mod 4 是迴圈數列,其最小正週期是 6:

  • 1, 1, 2, 3, 1, 0, ...

數列 g(n) mod 10 是迴圈數列,其最小正週期是 30:

  • 2,4,8,6,8,4,6,8,2,0,2,8,0,2,6,4,6,2,4,6,0,8,0,6,8,0,4,2,4,0, ...

所以猜想1是正確的。

猜想2應該也可以用類似的方法證明。

參考資料

  1. 圖靈社群:冪的一個公式(一)
  2. Wikipedia: Fibonacci number

相關文章