Fibonacci poj-3070
题目大意:求Fibonacci第n项。
注释:模数为10000,$1le n le 10^9$。
想法:矩阵题,用例题6的想法,我们构造矩阵
$egin{pmatrix} 0 & 1 \ 1 & 1 end{pmatrix}$
然后,我们快速幂即可。
附上lijinnn的版子
struct Matr { int a[4][4]; Matr(){memset(a,0,sizeof a);} Matr operator *(const Matr &z) { Matr re; int p=2; for(int i=0;i<p;++i) { for(int j=0;j<p;++j) { for(int k=0;k<p;++k) { re.a[i][j]=(re.a[i][j]+a[i][k]*z.a[k][j])%mod; } } } return re; } };
这是一种重载运算符的方式,我开始用的是函数。但是在快速幂的时候确实有些慢(如果直接传参的话)。感谢lijinnn(吉林队长)。
其中,矩阵从零开始的空间优化特别多!此题没有...因为都没怎么开矩阵
最后,附上丑陋的代码... ...
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> #define mod 10000 using namespace std; struct Matr { int a[3][3]; Matr(){memset(a,0,sizeof a);} Matr operator *(const Matr &z)//重定义运算符 { Matr re; int p=2; for(int i=0;i<p;++i) { for(int j=0;j<p;++j) { for(int k=0;k<p;++k) { re.a[i][j]=(re.a[i][j]+a[i][k]*z.a[k][j])%mod; } } } return re; } }; Matr quick_power(int x)//快速幂 { Matr ori; for(int i=0;i<=1;i++) { for(int j=0;j<=1;j++) { ori.a[i][i]=1; } } Matr k; k.a[0][1]=k.a[1][0]=k.a[1][1]=1; while(x) { if(x&1) ori=ori*k; k=k*k; x>>=1; } return ori; } int main() { int n; while(1) { scanf("%d",&n); if(n==-1) return 0; Matr s; s=quick_power(n); Matr ans; ans.a[0][0]=-1; ans=ans*s; printf("%d ",-ans.a[0][1]);//为了方便,我的初始矩阵用的是负数为的是如果求第i项,快速幂i次即可 //但是由于开始是负数,所以需要在最后乘上-1 } }
小结:矩阵好东西,推荐自己的blog 矩阵算法学习摘记