在斐波那契数列中,Fib0=0,Fib1=1,Fibn=Fibn−1+Fibn−2(n>1)Fib0=0,Fib1=1,Fibn=Fibn−1+Fibn−2(n>1)。
给定整数n,求Fibnmod10000Fibnmod10000。
输入格式
输入包含多组测试用例。
每个测试用例占一行,包含一个整数n。
当输入用例n=-1时,表示输入终止,且该用例无需处理。
输出格式
每个测试用例输出一个整数表示结果。
每个结果占一行。
数据范围
0≤n≤2∗109
输入样例:
0
9
999999999
1000000000
-1
输出样例:
0
34
626
6875
思路:由于n的范围达到了1e9,所以就算递推o(n)的做法也无法满足时间的要求,所以这里用到了矩阵乘法,就是把这种递推的运算用一个递推矩阵参与的矩阵乘法模拟,因为矩阵可以一次存储多个数字,所以极大的减少了计算的状态,简单地说,这里就是用一个矩阵a[2][2]初始等于={{0,1},{1,1}},a就是递推矩阵,让f[2]={0,1},(fib数列的前两个数),所以f[0]=fib(n),f[1]=fib(n+1),让f右乘一个a后,相当于:
f[0]=0*fib(n)+1*fib(n+1)=fib(n+1)
f[1]=1*fib(n)+1*fib(n+1)=fib(n+2)
这样f就变为了下一状态,f[0]=fib(n+1),f[1]=fib(n+2),以此类推,最终f[0]的结果即为答案。
注:矩阵相乘时,可用快速幂的方法优化,具体见代码。
#include <iostream>
#include <cstring>
#define int long long
using namespace std;
const int mod=1e4;
int n;
void mul(int f[2],int a[2][2])
{
int c[2];
memset(c,0,sizeof c);
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
c[i]=(c[i]+f[j]*a[j][i])%mod;
}
}
memcpy(f,c,sizeof c);
}
void mulself(int a[2][2])
{
int c[2][2];
memset(c,0,sizeof c);
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
for(int k=0;k<2;k++){
c[i][j]=(c[i][j]+a[i][k]*a[k][j])%mod;
}
}
}
memcpy(a,c,sizeof c);
}
int qmi(int n)
{
int f[2]={0,1};
int a[2][2]={{0,1},{1,1}};
while(n){
if(n&1) mul(f,a);
mulself(a);
n>>=1;
}
return f[0];
}
signed main()
{
while(cin>>n,n!=-1){
cout<<qmi(n)<<endl;
}
return 0;
}