Fibonacci数列矩阵表示 与 快速幂方法

来源:互联网 发布:制作新闻联播视频软件 编辑:程序博客网 时间:2024/05/22 03:13

问题背景:

http://soj.sysu.edu.cn/1863

    给定N,M,求Fn % m的结果。

F[0]=0;
F[1]=1;
F[n]=F[n-1]+F[n-2], for n>1


如果用公式递推,由于n很大,超过Int的范围并且递推时间复杂度是O(n).


解题思路:

  • Fibonacci数列的矩阵表示:
,矩阵的初始值是
  • 因此需要求矩阵的幂,问题分解为两部分,矩阵乘法 + 快速幂;采用【快速幂】的方法,原理如下:

b 为偶数时,a^b =a^(b/2) * a^(b/2), 

b 为奇数时,a^b =a*a^(b-1)

所以问题就转化为求a^(b/2)

<pre name="code" class="cpp">matrix fastMod(int n){if(n == 1)return base;/*matrix temp = base;          matrix ans;          ans[0][0] = ans[1][1] = 1; ans[0][1] = ans[1][0] =0;            while(n){<span></span>if( n & 1)   //如果n是奇数<span></span>ans = multiply(temp, ans);<span></span>n >>= 1;   //相当于n除以2<span></span>temp = multiply(temp, temp);           }           return temp;<span></span>}非递归方法*/if(n & 1)return multiply(base, fastMod(n-1));else{matrix temp = fastMod(n>>1);return multiply(temp, temp);}}


            
数据结构:
struct matrix{int m[2][2];}base;   //Fibonacci数列矩阵乘法表示的初始值

代码如下:
#include<iostream>#include<vector>using namespace std;struct matrix{int arr[2][2];}base;   //Fibonacci数列矩阵乘法表示的初始值int m;//矩阵乘法函数matrix multiply(matrix a, matrix b){matrix temp;temp.arr[0][0] = (a.arr[0][0]*b.arr[0][0] + a.arr[0][1]*b.arr[1][0]) % m;    <span style="white-space:pre"></span>temp.arr[0][1] = (a.arr[0][0]*b.arr[0][1] + a.arr[0][1]*b.arr[1][1]) % m;      <span style="white-space:pre"></span>temp.arr[1][0] = (a.arr[1][0]*b.arr[0][0] + a.arr[1][1]*b.arr[1][0]) % m;      <span style="white-space:pre"></span>temp.arr[1][1] = (a.arr[1][0]*b.arr[0][1] + a.arr[1][1]*b.arr[1][1]) % m;  return temp;}matrix fastMod(int n){if(n == 1)return base;/*matrix temp = base;          matrix ans;          ans[0][0] = ans[1][1] = 1; ans[0][1] = ans[1][0] =0;            while(n){<span style="white-space:pre"></span>if( n & 1)   //如果n是奇数<span style="white-space:pre"></span>ans = multiply(temp, ans);<span style="white-space:pre"></span>n >>= 1;   //相当于n除以2<span style="white-space:pre"></span>temp = multiply(temp, temp);           }           return temp;<span style="white-space:pre"></span>}非递归方法*/if(n & 1)return multiply(base, fastMod(n-1));else{matrix temp = fastMod(n>>1);return multiply(temp, temp);}}int main(){int t;unsigned int n;//matrix ans;cin >> t;while(t--){cin >> n >> m;if(n==0)cout << 0 << endl;else{//初始赋值base.arr[0][0] = base.arr[0][1] = base.arr[1][0] = 1;base.arr[1][1] = 0;cout << fastMod(n).arr[0][1] % m << endl;}}return 0;}


0 0