洛谷P1962 斐波那契数列
2017-10-31 16:41
344 查看
题目背景
大家都知道,斐波那契数列是满足如下性质的一个数列:
• f(1)=1
• f(2)=1
• f(n)=f(n−1)+f(n−2)(n≥2且n为整数)
题目描述
请你求出 f(n) mod 1000000007 的值。
输入格式
第1行:一个整数n
输出格式
第1行:f(n) mod 1000000007 的值
输入样例#1
5
输出样例#1
5
输入样例#2
10
输出样例#2
55
说明
对于 60% 的数据:n≤92。
对于 100% 的数据:n在long long(INT64)范围内。
思路
矩阵乘法优化。(友情提示:一个n×m的矩阵A和一个m×r的矩阵相乘,得出一个n×r的矩阵,这个矩阵的i行j列为∑mk=1,矩阵乘法不满足交换律,但满足结合律和分配律)
首先,斐波那契数列的递推式为fi=fi−1+fi−2,那么设有一个矩阵A:[fi−1fi−2]要依据这个矩阵乘上一个矩阵trans求出另外一个矩阵B:[fifi−1]求这个矩阵trans。
显然,trans这个矩阵要为[0111]才能满足A×trans=b
那么这样如果暴力做显然是O(n)的,并没有优化。
考虑到[f2f1]×[0111]n−2=[fnfn−1]并且矩阵乘法满足结合律,那么可以用快速幂优化。
最终时间复杂度O(logn)
代码
大家都知道,斐波那契数列是满足如下性质的一个数列:
• f(1)=1
• f(2)=1
• f(n)=f(n−1)+f(n−2)(n≥2且n为整数)
题目描述
请你求出 f(n) mod 1000000007 的值。
输入格式
第1行:一个整数n
输出格式
第1行:f(n) mod 1000000007 的值
输入样例#1
5
输出样例#1
5
输入样例#2
10
输出样例#2
55
说明
对于 60% 的数据:n≤92。
对于 100% 的数据:n在long long(INT64)范围内。
思路
矩阵乘法优化。(友情提示:一个n×m的矩阵A和一个m×r的矩阵相乘,得出一个n×r的矩阵,这个矩阵的i行j列为∑mk=1,矩阵乘法不满足交换律,但满足结合律和分配律)
首先,斐波那契数列的递推式为fi=fi−1+fi−2,那么设有一个矩阵A:[fi−1fi−2]要依据这个矩阵乘上一个矩阵trans求出另外一个矩阵B:[fifi−1]求这个矩阵trans。
显然,trans这个矩阵要为[0111]才能满足A×trans=b
那么这样如果暴力做显然是O(n)的,并没有优化。
考虑到[f2f1]×[0111]n−2=[fnfn−1]并且矩阵乘法满足结合律,那么可以用快速幂优化。
最终时间复杂度O(logn)
代码
#include <cstdio> const int maxn=10; const int mo=1000000007; struct matrix { long long a[maxn+1][maxn+1],r,c; matrix operator *(const matrix &other) { matrix res; res.r=r; res.c=other.c; for(int i=1; i<=res.r; i++) { for(int j=1; j<=res.c; j++) { long long sum=0; for(int k=1; k<=c; k++) { sum+=a[i][k]*other.a[k][j]; sum%=mo; } res.a[i][j]=sum; } } return res; } }; long long n; matrix t,c,ans; matrix quickpow(matrix a,long long b,int m) { matrix res; res.c=a.c; res.r=a.r; for(int i=1; i<=res.r; i++) { for(int j=1; j<=res.c; j++) { res.a[i][j]=0; } res.a[i][i]=1; } while(b) { if(b&1) { res=res*a; b--; } b/=2; a=a*a; } return res; } inline long long read() { long long x=0; int f=1; char ch=getchar(); while((ch<'0')||(ch>'9')) { if(ch=='-') { f=-f; } ch=getchar(); } while((ch>='0')&&(ch<='9')) { x=x*10+ch-'0'; ch=getchar(); } return x*f; } int main() { n=read(); if(n==1ll) { printf("1\n"); return 0; } t.r=1; t.c=2; t.a[1][1]=1; t.a[1][2]=1; c.r=2; c.c=2; c.a[1][1]=0; c.a[1][2]=1; c.a[2][1]=1; c.a[2][2]=1; ans=t*quickpow(c,n-2,mo); printf("%lld\n",ans.a[1][2]); return 0; }
相关文章推荐
- [洛谷1962]斐波那契数列
- 【洛谷1962】 斐波那契数列
- 【洛谷1962】 斐波那契数列
- [luoguP1962] 斐波那契数列(矩阵快速幂)
- 洛谷_P1962_斐波那契数列
- 洛谷11月月赛 T3 斐波那契数列
- AC日记——斐波那契数列(升级版) 洛谷 P2626
- 洛谷 P1962 斐波那契数列
- P2626 斐波那契数列(升级版) 洛谷(2626)
- 洛谷P1962 斐波那契数列
- 洛谷 P2626 斐波那契数列(升级版)
- 洛谷P1962 斐波那契数列【矩阵运算】
- 洛谷 P2626 斐波那契数列(升级版)
- 洛谷P1962 斐波那契数列
- LuoguP1962 斐波那契数列 解题报告【矩阵快速幂】
- 洛谷P1962 斐波那契数列 || P1349 广义斐波那契数列[矩阵乘法]
- 洛谷—— P1962 斐波那契数列
- 【洛谷P1962 斐波那契数列】矩阵快速幂+数学推导
- Luogu 1962 斐波那契数列(矩阵,递推)
- 矩阵快速幂模板及其应用(洛谷3390)(洛谷1962)