斐波那契数列 学习笔记
#1 定义
斐波那契数列
斐波那契数列(The Fibonacci sequence,OEIS A000045)的定义如下:
该数列的前几项如下:
* 卢卡斯数列
卢卡斯数列(The Lucas sequence,OEIS A000032)的定义如下:
该数列的前几项如下:
NOTE
研究斐波那契数列,很多时候需要借助卢卡斯数列为工具。
#2 斐波那契数列通项公式
第
2.1 解析解
解析解即公式解。我们有斐波那契数列的通项公式(Binet's Formula
这个公式可以很容易地用归纳法证明,当然也可以通过生成函数的概念推导,或者解一个方程得到。
简化
不难发现,这个公式分子的第二项总是小于
这里的中括号表示取离它最近的整数。
这两个公式在计算的时候要求极高的精确度,因此在实践中很少用到。但是请不要忽视!结合模意义下二次剩余和逆元的概念,在 OI 中使用这个公式仍是非常有用的。
2.2 矩阵形式
斐波那契数列的递推可以用矩阵乘法的形式表达:
设
于是我们可以用矩阵乘法在
快速倍增法
使用上面的方法我们可以得到以下等式:
于是可以通过这样的方法快速计算两个相邻的斐波那契数(常数比矩乘小
pair<int, int> fib(int n) {
if (n == 0)
return {0, 1};
auto p = fib(n >> 1);
int c = p.first * (2 * p.second - p.first);
int d = p.first * p.first + p.second * p.second;
if (n & 1)
return {d, c + d};
else
return {c, d};
}
#3 模意义下周期性
考虑模
3.1 皮萨诺周期
模
皮萨诺周期总是不超过
当需要计算第
容易验证,斐波那契数模
显然,如果
计算周期还需要以下结论:
结论 1:对于奇素数 , 是斐波那契数模 的周期。即,奇素数 的皮萨诺周期整除 。
证明:
此时
由二项式展开:
因为
结论 2:对于奇素数 , 是斐波那契数模 的周期。即,奇素数 的皮萨诺周期整除 。
证明:
此时
由二项式展开:
模
于是
结论 3:对于素数 , 是斐波那契数模 的周期,等价于 是斐波那契数模 的周期。特别地, 是模 的皮萨诺周期,等价于 是模 的皮萨诺周期。
证明:
这里的证明需要把
由于:
因此:
因为反方向也可以推导,所以
当
当
代入
因此也等价于
因为周期等价,所以最小正周期也等价。
三个结论证完。据此可以写出代码:
struct prime {
unsigned long long p;
int times;
};
struct prime pp[2048];
int pptop;
unsigned long long get_cycle_from_mod(
unsigned long long mod) // 这里求解的只是周期,不一定是最小正周期
{
pptop = 0;
srand(time(nullptr));
while (n != 1) {
__int128_t factor = (__int128_t)10000000000 * 10000000000;
min_factor(mod, &factor); // 计算最小素因数
struct prime temp;
temp.p = factor;
for (temp.times = 0; mod % factor == 0; temp.times++) {
mod /= factor;
}
pp[pptop] = temp;
pptop++;
}
unsigned long long m = 1;
for (int i = 0; i < pptop; ++i) {
int g;
if (pp[i].p == 2) {
g = 3;
} else if (pp[i].p == 5) {
g = 20;
} else if (pp[i].p % 5 == 1 || pp[i].p % 5 == 4) {
g = pp[i].p - 1;
} else {
g = (pp[i].p + 1) << 1;
}
m = lcm(m, g * qpow(pp[i].p, pp[i].times - 1));
}
return m;
}