Problem Address:http://acm.hdu.edu.cn/showproblem.php?pid=1005
【题意】
f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7
1 <= A, B <= 1000, 1 <= n <= 100,000,000
【思路】
由于这道题只需要mod7,所以可以用循环节之类的方法做。
但也可以用矩阵优化递推的方法简单地做出来。
下面描述一下矩阵的做法。
f(n+2) = A*C(n-1)*B(1)
其中A、B、C均为矩阵。
A=
(a1,a2)
B=
(1)
(2)
C=
(a1, a2)
(1 , 0 )
关键部分是算出C的n-1次方,得出结果后再由上式计算出f(n+2)的值,而f(1)、f(2)的值为已知。
详细请参考:http://wenku.baidu.com/view/b396f5c689eb172ded63b7b8.html
C(n)可以使用快速幂的形式计算。矩阵的快速幂类似于普通整数的快速幂。
为了方便,可以定义矩阵的结构体,重载乘法以及幂运算的运算符。
具体看代码。
【代码】
#include <iostream>
using namespace std;
const int P = 7;
struct matrix
{
int mat[2][2];
int N;
void init(int a, int b)
{
N = 2;
mat[0][0] = a; mat[0][1] = b;
mat[1][0] = 1; mat[1][1] = 0;
}
matrix operator *(matrix B)
{
matrix C;
C.N = N;
memset(C.mat, 0, sizeof(C.mat));
int i, j, k;
for (i=0; i<N; i++)
{
for (j=0; j<N; j++)
{
if (mat[i][j])
{
for (k=0; k<N; k++)
{
C.mat[i][k] = (C.mat[i][k]+mat[i][j]*B.mat[j][k])%P;
}
}
}
}
return C;
}
matrix operator ^ (int n)
{
matrix C;
C.N = N;
memset(C.mat, 0, sizeof(C.mat));
int i;
for (i=0; i<N; i++) C.mat[i][i] = 1;
while(n)
{
if (n&1) C = C*(*this);
*this = (*this)*(*this);
n >>= 1;
}
return C;
}
int getvalue(int a1, int a2, int a, int b)
{
return (a2*(a*mat[0][0]+b*mat[1][0])+a1*(a*mat[0][1]+b*mat[1][1]))%P;//这里本来的a1和a2位置颠倒了,现已改过来
}
};
int solve(int a1, int a2, int a, int b, int n)
{
if (n==1) return a1;
else if (n==2) return a2;
n -= 2;
matrix A;
A.init(a, b);
A = A^(n-1);
return A.getvalue(a1, a2, a, b);
}
int main()
{
int a, b, n;
while(scanf("%d %d %d", &a, &b, &n)!=EOF)
{
if (n==0 && a==0 && b==0) break;
printf("%d\n", solve(1, 1, a, b, n));
}
return 0;
}
注:之前由于是直接使用斐波那契数列,a1=a2=1,所以没有发现错误。