链接
l
u
o
g
u
P
1962
luogu\ P1962
luogu P1962
s
s
l
1529
ssl\ 1529
ssl 1529
题目描述
形如 1 1 2 3 5 8 13 21 34 55 89 144…的数列,求斐波拉契数列的第n项。
输入
n ( 1 < n < 2 31 ) n (1< n <2^{31}) n(1<n<231)
输出
输出 F n m o d 1 0 9 + 7 F_n \bmod 10^9 + 7 Fnmod109+7
样例输入
10
样例输出
55
思路
矩阵乘法
我们设一个矩阵
f
i
b
(
n
−
1
)
fib(n - 1)
fib(n−1)为{
f
n
−
1
,
f
n
−
2
f_{n - 1}, f_{n - 2}
fn−1,fn−2}, 那么我们要得到
f
i
b
(
n
)
fib(n)
fib(n)
显然是
f
i
b
(
n
)
=
f
i
b
(
n
−
1
)
∗
B
fib(n) = fib(n - 1) * B
fib(n)=fib(n−1)∗B
B为一个矩阵
我们分开来考虑
首先是
f
n
f_n
fn,它是
f
n
−
1
+
f
n
−
2
f_{n - 1} + f_{n - 2}
fn−1+fn−2
所以
1 | |
---|---|
1 |
再考虑
f
i
b
(
n
)
fib(n)
fib(n)的第二个元素
f
n
−
1
f_{n-1}
fn−1
那就是原本
f
i
b
(
n
−
1
)
fib(n - 1)
fib(n−1)的第一个元素
因此就是
1 | 1 |
---|---|
1 | 0 |
那么我们考虑答案
其实就是
f
i
b
(
2
)
∗
B
n
−
2
fib(2) * B^{n-2}
fib(2)∗Bn−2
因为
n
<
=
2
n<=2
n<=2是不需要进行处理的
用快速幂求出答案即可
代码
P1962(mod = 1e9 + 7)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
const ll whd = 1e9 + 7;
ll n;
struct Matrix
{
ll a[3][3];
}ans, r;
Matrix operator *(Matrix a, Matrix b)
{
Matrix c;
for(int i = 1; i <= 2; ++i)
for(int j = 1; j <= 2; ++j)
c.a[i][j] = 0;
for(int i = 1; i <= 2; ++i)
for(int j = 1; j <= 2; ++j)
for(int k = 1; k <= 2; ++k)
c.a[i][j] = (c.a[i][j] + (a.a[i][k] * b.a[k][j]) % whd) % whd;
return c;
}//定义乘法的运算为矩阵的乘法运算
void ksm(ll n)
{
while(n)
{
if(n & 1) ans = ans * r;
r = r * r;
n >>= 1;
}
}//快速幂
void init()
{
r.a[1][1] = r.a[1][2] = r.a[2][1] = 1;
ans.a[1][1] = ans.a[1][2] = 1;
}//初始化
int main()
{
scanf("%lld", &n);
if(n < 3) {
printf("1");
return 0;
}
init();
ksm(n - 2);
printf("%lld", ans.a[1][1] % whd);
}
1529(mod = 1e4)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
const ll whd = 1e4;
ll n;
struct Matrix
{
ll a[3][3];
}ans, r;
Matrix operator *(Matrix a, Matrix b)
{
Matrix c;
for(int i = 1; i <= 2; ++i)
for(int j = 1; j <= 2; ++j)
c.a[i][j] = 0;
for(int i = 1; i <= 2; ++i)
for(int j = 1; j <= 2; ++j)
for(int k = 1; k <= 2; ++k)
c.a[i][j] = (c.a[i][j] + (a.a[i][k] * b.a[k][j]) % whd) % whd;
return c;
}
void ksm(ll n)
{
while(n)
{
if(n & 1) ans = ans * r;
r = r * r;
n >>= 1;
}
}
void init()
{
r.a[1][1] = r.a[1][2] = r.a[2][1] = 1;
ans.a[1][1] = ans.a[1][2] = 1;
}
int main()
{
scanf("%lld", &n);
if(n < 3) {
printf("1");
return 0;
}
init();
ksm(n - 2);
printf("%lld", ans.a[1][1] % whd);
}