POJ3070Fibonacci 矩阵快速幂

Fibonacci

Description

In the Fibonacci integer sequence, F 0 = 0 F_0=0 F0=0, F 1 = 1 F_1=1 F1=1, and F n = F n − 1 + F n − 2 F_n = F_{n-1}+F_{n-2} Fn=Fn1+Fn2for n > = 2 n>=2 n>=2. For example, the first ten terms of the Fibonacci sequence are:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …

An alternative formula for the Fibonacci sequence is

[ F n + 1 F n F n F n − 1 ] = [ 1 1 1 0 ] n \left[ \begin{matrix} F_{n+1} & F_{n}\\ F_{n} & F_{n-1} \end{matrix} \right]= \left[ \begin{matrix} 1&1\\ 1&0\\ \end{matrix} \right]^n [Fn+1FnFnFn1]=[1110]n
Given an integer n n n, your goal is to compute the last 4 digits of F n Fn Fn.

Input

The input test file will contain multiple test cases. Each test case consists of a single line containing n (where $0 ≤ n n n ≤ 1,000,000,000$). The end-of-file is denoted by a single line containing the number −1.

Output

For each test case, print the last four digits of F n Fn Fn. If the last four digits of F n Fn Fn are all zeros, print ‘0’; otherwise, omit any leading zeros (i.e., print $Fn $mod 10000).

Sample Input

0
9
999999999
1000000000
-1

Sample Output

0
34
626
6875

Hint

As a reminder, matrix multiplication is associative, and the product of two 2 × 2 matrices is given by
[ a 11 a 12 a 21 a 22 ] [ b 11 b 12 b 21 b 22 ] = [ a 11 b 11 + a 12 b 12 a 11 b 12 + a 12 b 22 a 21 b 11 + a 22 b 21 a 21 b 12 + a 22 b 22 ] \left[ \begin{matrix} a_{11} & a_{12}\\ a_{21} & a_{22} \end{matrix} \right]\left[ \begin{matrix} b_{11} & b_{12}\\ b_{21} & b_{22} \end{matrix} \right]= \left[ \begin{matrix} a_{11}b_{11}+a_{12}b_{12} & a_{11}b_{12}+a_{12}b_{22}\\ a_{21}b_{11}+a_{22}b_{21} & a_{21}b_{12}+a_{22}b_{22}\\ \end{matrix} \right] [a11a21a12a22][b11b21b12b22]=[a11b11+a12b12a21b11+a22b21a11b12+a12b22a21b12+a22b22]
Also, note that raising any 2 × 2 matrix to the 0th power gives the identity matrix:
[ a 11 a 12 a 21 a 22 ] 0 = [ 1 0 0 1 ] \left[ \begin{matrix} a_{11} & a_{12}\\ a_{21} & a_{22}\\ \end{matrix} \right]^{0}=\left[ \begin{matrix} 1 & 0\\ 0 & 1\\ \end{matrix} \right] [a11a21a12a22]0=[1001]


递推式: f ( n ) = a f ( n − 1 ) + b f ( n − 2 ) f(n) = af(n-1)+bf(n-2) f(n)=af(n1)+bf(n2)

[ f ( n + 1 ) f ( n ) ] = [ a b 1 0 ] ∗ [ f ( n ) f ( n − 1 ) ] = [ a b 1 0 ] n − 1 ∗ [ f ( 2 ) f ( 1 ) ] \left[ \begin{matrix} f(n+1)\\ f(n)\\ \end{matrix} \right]= \left[ \begin{matrix} a & b\\ 1 & 0\\ \end{matrix} \right]* \left[ \begin{matrix} f(n)\\ f(n-1)\\ \end{matrix} \right]= \left[ \begin{matrix} a & b\\ 1 & 0\\ \end{matrix} \right]^{n-1} * \left[ \begin{matrix} f(2)\\ f(1)\\ \end{matrix} \right] [f(n+1)f(n)]=[a1b0][f(n)f(n1)]=[a1b0]n1[f(2)f(1)]

本题的a=b=1

根据快速幂 求出矩阵的n-1次方 A = [ a b 1 0 ] n − 1 A=\left[\begin{matrix}a&b\\1&0\end{matrix}\right]^{n-1} A=[a1b0]n1

那么 f n = A [ 1 ] [ 0 ] ∗ f 2 + A [ 1 ] [ 1 ] ∗ f 1 f_n = A[1][0] * f_2 + A[1][1]*f_1 fn=A[1][0]f2+A[1][1]f1


#include <bits/stdc++.h>
using namespace std;
const int N = 105;
int n;//矩阵维数
int mod; //模数 
struct mat{
	int m[N][N];
	mat(){
		memset(m,0,sizeof(m));
		for(int i=0;i<N;i++){
			m[i][i]=1; //初始化单位矩阵	
		}
	}
	//矩阵乘法 
	mat operator*(mat& a) {
		mat res;
		for(int i=0;i<n;i++)
			for(int j=0;j<n;j++)
			{
				res.m[i][j]=0;
				for(int k=0;k<n;k++)
					res.m[i][j] += m[i][k] * a.m[k][j];
				res.m[i][j] %= mod;
			}
		return res;
	}
};
mat fastPow(mat a,int k){  //矩阵快速幂 ★★★★
	mat res;
	while(k){
		if(k&1) res = res * a;
		a = a*a;
		k>>=1;
	}
	return res;
} 
int main()
{
	n=2;
	mod = 10000;
	mat res,a;
	res.m[0][0] = 1;
	res.m[0][1] = 1;
	res.m[1][0] = 1;
	res.m[1][1] = 0;
    int input;
	while(cin>>input && input != -1){
		if(input <= 0){
			cout<<0<<endl;
			continue;
		}
		a = fastPow(res,input-1);
		cout<<(a.m[1][0]+a.m[1][1])%mod<<endl;
	}
	return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值