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,所以没有发现错误。