Description
In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn = Fn − 1 + Fn − 2 for 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
Given an integer n, your goal is to compute the last 4 digits of Fn.
Input
The input test file will contain multiple test cases. Each test case consists of a single line containing n (where 0 ≤ 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 Fn. If the last four digits of 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
这个题是出题人好心,直接把规律给我们找出来了,那我们就只需要求那个矩阵的n次方,然后输出a[0][1]即可
1.先说说矩阵快速幂
为了类比快速幂,我们先写出快速幂的代码
快速幂求x的y次方,是把y看作二进制来的,矩阵快速幂也一样。
区别:
1.矩阵快速幂底数是矩阵,ren是矩阵
2.最终矩阵乘矩阵还是矩阵,也就是说函数返回矩阵,ans是矩阵
3.我们存答案的ans初始化应该是初等矩阵
所以涉及到矩阵的代码我们都要改
int pow_1(int x,int y){//x的y次方 int ren=x;int ans=1;while(y){if(y&1) ans*=ren;//取当前最末位的y,如果是1就继续乘ren ren*=ren;//下一位ren是当前ren的平方 1 2 4 8,这里8是x^4的平方,不是4的平方 y=y>>1;//y前进一位 }return ans;
}
改完之后就是这样了
struct matrix
{LL x[2][2];
};
matrix mutimatrix(matrix a,matrix b)
{matrix temp; memset(temp.x,0,sizeof(temp.x)); for(int i=0;i<2;i++)for(int j=0;j<2;j++)for(int k=0;k<2;k++){temp.x[i][j]+=a.x[i][k]*b.x[k][j];temp.x[i][j]%=mod;}return temp;
}matrix k_powmatrix(matrix a,LL n)
{matrix temp;memset(temp.x,0,sizeof(temp.x));for(int i=0;i<2;i++)temp.x[i][i]=1;while(n){if(n&1)temp=mutimatrix(temp,a);a=mutimatrix(a,a);n>>=1;}return temp;
}
这个出题人直接把意思说的明明白白的,直接求那个矩阵的n次方就ok
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define LL long long
const int mod=10000;
struct matrix
{LL x[2][2];
};
matrix mutimatrix(matrix a,matrix b)
{matrix temp; memset(temp.x,0,sizeof(temp.x)); for(int i=0;i<2;i++)for(int j=0;j<2;j++)for(int k=0;k<2;k++){temp.x[i][j]+=a.x[i][k]*b.x[k][j];temp.x[i][j]%=mod;}return temp;
}matrix k_powmatrix(matrix a,LL n)
{matrix temp;memset(temp.x,0,sizeof(temp.x));for(int i=0;i<2;i++)temp.x[i][i]=1;while(n){if(n&1)temp=mutimatrix(temp,a);a=mutimatrix(a,a);n>>=1;}return temp;
} int main()
{int n;while(cin>>n ){if(n==0) {cout<<"0\n";continue;}if(n==1||n==2) {cout<<"1\n";continue;}if(n==-1) return 0;matrix st;memset(st.x,0,sizeof(st.x));st.x[0][0]=1;st.x[0][1]=1;st.x[1][0]=1;st.x[1][1]=0;st=k_powmatrix(st,n);printf("%lld\n",(st.x[0][1]+mod)%mod);}
}
2.如何通过矩阵快速幂解决这种递推问题
先看普通斐波那契
参考:https://blog.csdn.net/wust_zzwh/article/details/52058209
f(n)=f(n-1)+f(n-2)
f(1)=f(2)=1
其实这个是个递推式,那么我们只要找到他的通项,就可以求出n为任何值时候的f(n)
那这个递推式我们看不出他是等比还是等差数列,通项也不会求,此时就需要用矩阵
因为矩阵有一个性质,一个常数矩阵乘以一个矩阵A(n),结果是矩阵B(n)
那如果A中各个元素对应于B中各个元素满足,A(n)=B(n-1),那这个整体就是个等比数列啊
我们设an=
上面看作是q*a(n-1)=an,由等比数列通项公式得到
q^(n-1)*a1=an
现在q我们已经有了,就剩找a1了,a1我们都会求,带特殊值么,假设n=2,a2=q*a1,然后我们就求出a1了,所以之后求an就先求q^(n-1),再求q^(n-1) *a1
因为我是学过线性代数的,其实这有个大问题,矩阵的左乘右乘结果不一样,为了方便起见,我们通项乘的次序应该和第一个递推式的次序一样
还有个例子
f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.
Given A, B, and n, you are to calculate the value of f(n).
图片来自:https://www.cnblogs.com/Blackops/p/5468284.html
通过这一题我们明白一个事情,那就是对我们那个矩阵数列的优化,2* 1矩阵可以写成2* 2矩阵,这样的话我们不用再弄一个函数去求2* 1矩阵*2*2矩阵了
还有一点,关于n那个次幂的事,这都是看a1对应的那个n是几,根小学学的等比数列一样一样的。。
还有个小窍门,我们不用一上来就推f(n),可以通过f(1),f(2)推f(3),推完之后把3变成n,1变成n-2,2变成n-1,然后带4验证。如果是,那就是,然后继续ok
参考代码:
https://blog.csdn.net/elbadaernu/article/details/77899130
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define LL long long
const int mod=7;
struct matrix
{LL x[2][2];
};
matrix mutimatrix(matrix a,matrix b)
{matrix temp; memset(temp.x,0,sizeof(temp.x)); for(int i=0;i<2;i++)for(int j=0;j<2;j++)for(int k=0;k<2;k++){temp.x[i][j]+=a.x[i][k]*b.x[k][j];temp.x[i][j]%=mod;}return temp;
}matrix k_powmatrix(matrix a,LL n)
{matrix temp;memset(temp.x,0,sizeof(temp.x));for(int i=0;i<2;i++)temp.x[i][i]=1;while(n){if(n&1)temp=mutimatrix(temp,a);a=mutimatrix(a,a);n>>=1;}return temp;
} int main()
{int a,b,n;while(scanf("%d%d%d",&a,&b,&n)){if(!(a+b+n)) break;if(n<=2){printf("1\n");continue;}matrix st;memset(st.x,0,sizeof(st.x));st.x[0][0]=a;st.x[0][1]=1;st.x[1][0]=b;st.x[1][1]=0;matrix init;memset(init.x,0,sizeof(init.x));init.x[0][0]=1;init.x[0][1]=1;st=k_powmatrix(st,n-2);st=mutimatrix(init,st);printf("%lld\n",(st.x[0][0]+mod)%mod);}return 0; }