您的位置:首页 > 其它

LuoguP1962 斐波那契数列 解题报告【矩阵快速幂】

2017-10-19 21:09 417 查看
题目背景

大家都知道,斐波那契数列是满足如下性质的一个数列:

• 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在long long范围内,看来就只能用矩阵快速幂了。

怎么用矩阵快速幂呢?

我们知道,f[n]=f[n−1]∗1+f[n−2]∗1,f]n−1]=f[n−1]∗1+f[n−2]∗0。那么根据矩阵乘法的性质,就有:





(转自这篇博客

又因为f[1]=f[2]=1,所以我们不需要在意那个1*2的矩阵,直接算矩阵的^(n-1)就好了。

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=2,mod=1e9+7;
struct mat
{
ll c[N+5][N+5];
};
ll n;
mat mat_mul(mat a,mat b)
{
mat ret;
memset(ret.c,0,sizeof(ret.c));
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
for(int k=1;k<=N;k++)
ret.c[i][j]=(ret.c[i][j]%mod+a.c[i][k]*b.c[k][j]%mod)%mod;
return ret;
}
ll mat_pow()
{
mat base,ret;
n-=2;
memset(base.c,0,sizeof(base.c));
memset(ret.c,0,sizeof(ret.c));
base.c[1][2]=1,base.c[2][1]=1,base.c[1][1]=1;
base.c[2][2]=0;
ret.c[1][2]=1,ret.c[2][1]=1,ret.c[1][1]=1;
ret.c[2][2]=0;
for(ret;n;n>>=1,base=mat_mul(base,base))if(n&1)ret=mat_mul(ret,base);
return ret.c[1][1];
}
int main()
{
scanf("%lld",&n);
if(n==0){printf("0");return 0;}
if(n==1||n==2){printf("1");return 0;}
printf("%lld\n",mat_pow());
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: