矩阵快速幂
矩阵的快速幂是用来高效地计算矩阵的高次方的。将朴素的o(n)的时间复杂度,降到log(n)。
其算法本身,利用了之前运算的结果,让整个的运算过程呈现出一种二叉树从底层向上进行收拢的效果。
具体来说,当我们要计算A8的时候,我们朴素的算法是依次计算A*A*A*A*A*A*A*A,即第一步先算出A2然后算式变为A2*A*A*A*A*A*A*A,再变为A3*A*A*A*A*A,依次类推,最终得出A8的值。
而矩阵快速幂的算法则是,先算出A2再利用其结果进行下一步运算,即A*A*A*A*A*A*A*A会先变成A2*A2*A2*A2,之后在计算出A4,将算式变为A4*A4,之后算出A8,这样整个过程只进行了log(8)次,大大减少了运算过程。
这样的运算过程就像刚刚所说,是一种类似于二叉树从底层向上收拢的感觉。实际实现过程借助了计算机中 数的二进制表示。使用位运算则可以很好地得出结果。
51nod中的1242(戳我)即矩阵快速幂的模板题,大家可以用来练习
斐波那契数列的定义如下:
F(0) = 0
F(1) = 1
F(n) = F(n - 1) + F(n - 2) (n >= 2)
(1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, ...)
给出n,求F(n),由于结果很大,输出F(n) % 1000000009的结果即可。
Input
输入1个数n(1 <= n <= 10^18)。
Output
输出F(n) % 1000000009的结果。
Input示例
11
Output示例
89
AC代码:
#include <stdio.h> #include <cstring> #include <iostream> using namespace std; const long long INF=1000000009; struct node{ long long c[2][2]; }t; node mult(node a,node b){ node c={0}; for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++){ c.c[i][j]+=(a.c[i][k]*b.c[k][j])%INF; c.c[i][j]%=INF; } return c; } node pow(long long n){ node pt=t; if(n < 0) return pt; while(n){ if(n & 1){ pt=mult(pt,t); } t=mult(t,t); n=n>>1; } return pt; } int main(){ long long n; scanf("%lld",&n); t.c[0][0]=1; t.c[0][1]=1; t.c[1][0]=1; t.c[1][1]=0; node ans=pow(n-2); printf("%lld\n", ans.c[0][0] * 1); return 0; }