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

问题背景:

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值