sdutoj 1132 C/C++经典程序训练2---斐波那契数列 矩阵快速幂

缘起

日常浪费生命~ sdutoj 1132 C/C++经典程序训练2—斐波那契数列

分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
编写计算斐波那契(Fibonacci)数列的第n项函数fib(n)(n<40)。
数列:
f1=f2==1;
fn=fn-1+fn-2(n>=3)。

Input
输入整数n的值。

Output
输出fib(n)的值。

Sample Input
7

Sample Output
13

水水更健康~ DP做法是显然的~

这题纯粹是为了练习矩阵快速幂(其实dp快的多)~ 矩阵A是

1
2
3
4
{
{1,1},
{1,0}
}

则令 x[n]=(a_{n},a_{n-1})(n>1), 则

1
x[n]=A^{n-2}*x[2]

于是我们有

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//#include "stdafx.h"

#include <stdio.h>
#include <string.h>
//#define LOCAL

typedef long long LL;

int a[2][2] = {{1,1},{1,0}};

void m_mul(int a[2][2], int b[2][2]) // a*b 矩阵乘法
{
int ans[2][2];
memset(ans, 0, sizeof(ans));
for (int i = 0;i<2;i++)
{
for (int j = 0; j<2; j++)
{
for(int k = 0;k<2; k++)
{
ans[i][j]+=a[i][k]*b[k][j];

}
}
}
memcpy(a, ans, sizeof(ans));
}

void ksm(int a[2][2], int b) // 矩阵快速幂 a^b
{
int ans[2][2] = {{1,0},{0,1}};
while(b)
{
if (b&1)
{
m_mul(ans, a);
}
if (b>1)
{
m_mul(a,a);
}
b>>=1;
}
memcpy(a, ans, sizeof(ans));
}

LL fib(LL n)
{
n-=2;
ksm(a, n);
return a[0][0]+a[0][1];
}

int main()
{
#ifdef LOCAL
freopen("d:\\data.in", "r", stdin);
#endif
LL n;
scanf("%lld", &n);
printf("%lld\n", fib(n));
return 0;
}

ac情况

6556503 yfs 1132 Accepted 0 ms 148 KiB g++ 882 B 2019-09-20 12:41:38