1184: 帮我求算一下斐波那契数吧
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 261 Solved: 57
[Submit][Status][Web Board]
Description
AYY小朋友对斐波那契数非常感兴趣,他知道f[1]=1,f[2]=1,并且从第三个斐波那契数开始f[n]=f[n-2]+f[n-1](n>=3),可是AYY小朋友只会计算前十个斐波那契数,因此他向你请教,让你帮忙计算第N个斐波那契数是多少,但是由于结果非常大,只需告诉他对1000000007取模的结果。
Input
多组测试数据
每行一个n(1<=n<=2^32-1)
Output
输出第n个斐波那契数的结果(对1000000007取模)
Sample Input
1
10
100
1000
10000
Sample Output
1
55
687995182
517691607
271496360
HINT
Source
【解析】
如果每次用递推公式,显而易见是会超时的 (1<=n<=2^32-1),预处理打表的话,上亿肯定内存超限了。那就只能引入新方法,快速幂矩阵了。
之前已经了解过整数快速幂了,则用相似的原理,矩阵也能快速幂
直接先看代码的实现
struct Matrix
{
int a[maxn][maxn];
}ans, res;
Matrix Mulit(Matrix A, Matrix B, int n)//矩阵A,B为同n阶方阵
{
Matrix temp;//用于存放A*B的结果
memset(temp.a, 0, sizeof(temp.a));
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
for (int k = 1; k <= n; k++)
temp.a[i][k] += A.a[i][k] * B.a[k][j];
return temp;
}
void QuickPower(int N, int n)
{
memset(ans.a, 0, sizeof(ans.a));
for (int i = 1; i <= n; i++)ans.a[i][i] = 1;
while (N)
{
if (N & 1)
ans = Mulit(ans, res, n);
res = Mulit(res, res, n);
N = N >> 1;
}
}
如何运用呢,最经典的用法就是此题。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 4;
const ll mod = 1000000007;
struct Matrix
{
ll m[maxn][maxn];
}ans,res;
Matrix Mulit(Matrix a, Matrix b, ll n)
{
Matrix temp;
for (ll i = 1; i <= n; i++)
for (ll j = 1; j <= n; j++)
temp.m[i][j] = 0;
for (ll i = 1; i <= n; i++)
for (ll j = 1; j <= n; j++)
for (ll k = 1; k <= n; k++)
temp.m[i][j] = (temp.m[i][j] + ((a.m[i][k] % mod) * b.m[k][j]%mod)) % mod;
return temp;
}
ll QuickPower(ll N, ll n)
{
for (ll i = 1; i <= n; i++)
for (ll j = 1; j <= n; j++)
{
if (i == j)ans.m[i][j] = 1;
else ans.m[i][j] = 0;
}
memset(res.m, 0, sizeof(res.m));
res.m[1][1] = 1;
res.m[1][2] = 1;
res.m[2][1] = 1;
res.m[2][2] = 0;
while (N)
{
if (N & 1)
ans = Mulit(ans, res, n);
res = Mulit(res, res, n);
N = N >> 1;
}
Matrix ok;
ok.m[1][1] = ok.m[2][1] = 1;
ok.m[1][2] = ok.m[2][2] = 0;
ok = Mulit(ans, ok, n);
return ok.m[1][1];
}
int main()
{
ll n;
while (~scanf("%lld", &n))
{
if (n <= 2)
printf("1\n");
else
printf("%lld\n", QuickPower(n - 2, 2));
}
return 0;
}