题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1005
题目大意:
给你一个递推公式,求出第n项。由于某项可能太大,所以取余7
解题思路:
矩阵二分幂的经典运用。
代码如下:
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<climits>
using namespace std;
#define CLR(arr, what) memset(arr, what, sizeof(arr))
typedef long long LL;
const LL Size = 3;
const LL MOD = 7; //取余
class Matrix67
{
public:
Matrix67(const LL ff1, const LL ff2, const LL aa, const LL bb, const LL cc, const LL nn); //构造函数
void copymat(LL mata[Size][Size], LL matb[Size][Size]); //矩阵复制:后->前
void binary(LL n); //矩阵二分幂:次数
void multiply(LL mata[Size][Size], LL matb[Size][Size]); //矩阵连乘
LL result(); //打印结果
private:
LL f1, f2, a, b, c, n;
LL mat[Size][Size], temp[Size][Size], mid[Size][Size]; //二分幂、递推、单位矩阵
};
Matrix67::Matrix67(const LL ff1, const LL ff2, const LL aa, const LL bb, const LL cc, const LL nn)
{
CLR(mat, 0); CLR(temp, 0); CLR(mid, 0);
f1 = ff1, f2 = ff2, a = aa, b = bb, c = cc, n = nn;
mat[0][1] = aa, mat[1][0] = 1, mat[1][1] = bb, mat[2][1] = 1, mat[2][2] = 1; //初始化单位矩阵
temp[0][0] = ff1, temp[0][1] = ff2, temp[0][2] = cc; //初始化递推矩阵
copymat(mid, mat);
}
void Matrix67::copymat(LL mata[Size][Size], LL matb[Size][Size])
{
for(int i = 0; i < Size; ++i)
for(int j = 0; j < Size; ++j)
mata[i][j] = matb[i][j];
}
void Matrix67::binary(LL n)
{
if(n == 1)
return ;
binary(n >> 1);
multiply(mat, mat);
if(n & 1) //奇次幂
multiply(mat, mid);
}
void Matrix67::multiply(LL mata[Size][Size], LL matb[Size][Size])
{
LL sum, tempmat[Size][Size];
for(int i = 0; i < Size; ++i)
{
for(int j = 0; j < Size; ++j)
{
sum = 0;
for(int k = 0; k < Size; ++k)
sum = (sum + mata[i][k] * matb[k][j]) % MOD;
tempmat[i][j] = (sum + MOD) % MOD;
}
}
copymat(mata, tempmat);
}
LL Matrix67::result()
{
if(n > 1)
{
binary(n - 1);
multiply(temp, mat);
}
return (temp[0][0] % MOD + MOD) % MOD; //temp[0][1]是f(n+1),注意~
}
int main()
{
LL a, b, n;
while(scanf("%lld%lld%lld", &a, &b, &n) && a && b && n)
{
Matrix67 m(1, 1, b, a, 0, n); //af(n-1)+bf(n-2),顺序调换~~
printf("%lld\n",m.result() % MOD);
}
return 0;
}