洛谷P1962 斐波那契数列

题目:https://www.luogu.org/problemnew/show/1962

题目背景

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

• 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)范围内。

 

解析

给了60分的暴力分,美滋滋= ̄ω ̄=

那么剩下的40分怎么办Σ( ° △ °|||)︴

别告诉我你要打一个辣么大的表( ﹁ ﹁ ) ~→

好吧,这就需要一个重要的知识点叫做矩阵乘法。

矩阵乘法不会的,请咨询度娘吧23333333333333.

矩阵乘法满足结合律哦。

我们可以把状态转移方程转化成矩阵相乘,然后,

中间乘的矩阵都是一样的哦。

那么,想到什么了吗(⊙ω⊙)

对啦,就是快速幂啦(∩_∩)

矩阵快速幂与快速幂的做法很相似哦!相信大佬们一定会的(~ ̄▽ ̄)~

好了,蒟蒻的代码如下了:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 #define ll long long
 8 #define mod 1000000007
 9 struct submix{
10     ll a[5][5];
11 };
12 submix operator * (submix x,submix y){
13     submix res;
14     memset(res.a,0,sizeof(res.a));
15     for (ll k=1;k<=2;++k){
16         for (ll i=1;i<=2;++i){
17             for (ll j=1;j<=2;++j){
18                 res.a[i][j]=(res.a[i][j]+x.a[i][k]*y.a[k][j])%mod;
19             }
20         }
21     } 
22     return res;
23 } 
24 ll f[1010];
25 ll n;
26 submix ori,enm;
27 submix ksm(submix x,ll k){
28     submix res=ori;
29     while (k){
30         if (k&1){
31             res=res*x;
32         }
33         x=x*x;
34         k=k/2;
35     }
36     return res;
37 }
38 int main(){
39     cin>>n;
40     if (n==1){
41         cout<<"1";
42         return 0;
43     }
44     if (n==2){
45         cout<<"1";
46         return 0;
47     }
48     ori.a[1][1]=1;
49     ori.a[1][2]=1;
50     ori.a[2][1]=1;
51     ori.a[2][2]=0;
52     enm=ksm(ori,n-3);
53     /*cout<<enm.a[1][1]<<endl;
54     cout<<enm.a[1][2]<<endl;
55     cout<<enm.a[2][1]<<endl;
56     cout<<enm.a[2][2]<<endl;*/
57     cout<<(enm.a[1][1]+enm.a[2][1])%mod;
58     return 0;
59 }
View Code

注释语句是我检验输出的,就无视掉吧233

posted @ 2017-11-06 22:16  lonlyn  阅读(203)  评论(0编辑  收藏  举报