题意
M斐波那契数列F[n]是一种整数数列,它的定义如下:
F[0] = a
F[1] = b
F[n] = F[n-1] * F[n-2] ( n > 1 )
现在给出a, b, n,你能求出F[n]的值吗?
思路
写出几项便发现,a 的指数是 fib[n - 1], b 的指数是 fib[n],实际上是求斐波那契数列+快速幂。
费马小定理
特别的,mod 是素数,故可以利用费马小定理。
a^(p-1)≡1(mod p)
特别注意!本题中应用费马小定理的指数是通过矩阵快速幂求得的。在快速幂中的mod 都得是 mod - 1!而不能在求出结果后搞一个 % (mod - 1)!这太傻了。是的,太傻了。
题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=4549
AC代码
#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
typedef long long LL;
typedef vector<LL> vec;
typedef vector<vec> mat;
int mod = 1000000007;
int a, b, n;
mat mul(mat A, mat B)
{
mat C(A.size(), vec(B[0].size()));
for(int i= 0; i< A.size(); i++)
for(int k= 0; k< B.size(); k++)
for(int j= 0; j< B[0].size(); j++)
C[i][j] = (C[i][j] + A[i][k] * B[k][j] % mod) % mod;
return C;
}
mat pow(mat A, LL n)
{
mat B(A.size(), vec(A.size()));
for(int i= 0; i< A.size(); i++)
B[i][i] = 1;
while(n > 0)
{
if(n & 1) B = mul(B, A);
A = mul(A, A);
n >>= 1;
}
return B;
}
int main()
{
while(scanf("%d %d %d", &a, &b, &n) != EOF)
{
if(n == 0){
cout << a % mod << endl;
continue;
}
mod = 1000000006;//mod - 1
mat A(2, vec(2));
A[0][0] = A[0][1] = A[1][0] = 1, A[1][1] = 0;
A = pow(A, n - 1);
mod ++;
mat t1 (1, vec(1));
t1[0][0] = a;
t1 = pow(t1, A[1][0]);
mat t2 (1, vec(1));
t2[0][0] = b;
t2 = pow(t2, A[0][0]);
cout << t1[0][0] * t2[0][0] % mod << endl;
}
return 0;
}