矩阵快速幂求斐波那契

基本形式

用矩阵分析

由上式分析可得:求F(n)等于求二阶矩阵的n - 1次方,结果取矩阵第一行第一列的元素。

快速幂优化

二阶矩阵的乘法满足结合律
设A,B,C都是任意的二阶矩阵
A(BC)=(AB)C

设n=N/2 结果向下取整

相当于

由上式可得:通过快速幂来减少运算次数

代码

矩阵(结构体构造)

1
2
3
4
struct node
{
LL a[2][2];//LL即long long
};

矩阵乘法

1
2
3
4
5
6
7
8
9
10
node mul(node x,node y)
{
node z;
memset(z.a,0,sizeof(z.a));
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
z.a[i][j]=(z.a[i][j]+x.a[i][k]*y.a[k][j])%mod;
return z;
}

求斐波那契第n个数

1
2
3
4
5
6
7
8
9
10
11
12
13
void quick(LL n)
{
node c,res;
c.a[0][0]=1,c.a[0][1]=1,c.a[1][0]=1,c.a[1][1]=0;
res.a[0][0]=1,res.a[0][1]=0,res.a[1][0]=0,res.a[1][1]=1;
while(n){
if(n&1)res=mul(res,c);
c=mul(c,c);
n=n>>1;
}
//cout<<res.a[0][0]<<" "<<res.a[0][1]<<" "<<res.a[1][0]<<" "<<res.a[1][1]<<endl;
cout<<res.a[0][1]<<endl;
}

即所求res矩阵中的a[0][1]

全部代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const double pi=acos(-1),eps=1e-10;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const int m=10007;

struct node
{
LL a[2][2];
};
LL n,sum;

node mul(node x,node y)
{
node z;
memset(z.a,0,sizeof(z.a));
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
z.a[i][j]=(z.a[i][j]+x.a[i][k]*y.a[k][j])%mod;
return z;
}

void quick(LL n)
{
node c,res;
c.a[0][0]=1,c.a[0][1]=1,c.a[1][0]=1,c.a[1][1]=0;
res.a[0][0]=1,res.a[0][1]=0,res.a[1][0]=0,res.a[1][1]=1;
while(n){
if(n&1)res=mul(res,c);
c=mul(c,c);
n=n>>1;
}
//cout<<res.a[0][0]<<" "<<res.a[0][1]<<" "<<res.a[1][0]<<" "<<res.a[1][1]<<endl;
cout<<res.a[0][1]<<endl;
}

int main()
{
cin>>n;
quick(n);

return 0;
}



斐波那契数列前n项求和

斐波那契数列前n项平方求和

用几何证明

分析

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const double pi=acos(-1),eps=1e-10;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const int m=10007;

struct node
{
LL a[2][2];
};
LL n,sum;

node mul(node x,node y)
{
node z;
memset(z.a,0,sizeof(z.a));
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
z.a[i][j]=(z.a[i][j]+x.a[i][k]*y.a[k][j])%mod;
return z;
}

void quick(LL n)
{
node c,res;
c.a[0][0]=1,c.a[0][1]=1,c.a[1][0]=1,c.a[1][1]=0;
res.a[0][0]=1,res.a[0][1]=0,res.a[1][0]=0,res.a[1][1]=1;
while(n){
if(n&1)res=mul(res,c);
c=mul(c,c);
n=n>>1;
}
//cout<<res.a[0][0]<<" "<<res.a[0][1]<<" "<<res.a[1][0]<<" "<<res.a[1][1]<<endl;
cout<<(res.a[0][0]%mod*res.a[0][1]%mod)%mod<<endl;
}

int main()
{
cin>>n;
quick(n);

return 0;
}



即res矩阵的a[0][0]与a[0][1]相乘(注意取模)