给你一个递推公式:
f(x)=a*f(x-2)+b*f(x-1)+c
并给你f(1),f(2)的值,请求出f(n)的值,由于f(n)的值可能过大,求出f(n)对1000007取模后的值。
注意:-1对3取模后等于2
在涛神的协助下构造出来的矩阵:(貌似发表了就格式乱了,空格用"..."表示)
Fn..........b...a...1......Fn-1
Fn-1..=..1...0...0......Fn-2
c ............0...0...1......c
第一次做矩阵幂的题,自己的理解就是:把二分幂的数与数相乘写成矩阵与矩阵相乘,矩阵幂适用与含有递推关系的递推式。
在乘的过程中需要注意的几点是:
构造出来的系数矩阵需要先进行二分幂的乘法,再去乘初始的矩阵。
矩阵乘法需要注意是谁乘谁,注意乘的顺序(a*b!=b*a)
注意取模
答案的矩阵形式上要和初试矩阵一致
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
typedef long long LL;
const LL mod = 1000007;
struct matrix
{
LL a[3][3];
}A;
matrix mul(matrix t1,matrix t2) ///矩阵乘法,注意取模
{
matrix tmp;
memset(tmp.a,0,sizeof tmp.a);
for(LL i = 0;i < 3;i++)
{
for(LL j = 0;j < 3;j++)
{
for(LL k = 0;k < 3;k++)
{
tmp.a[i][j] += ((t1.a[i][k]%mod)*(t2.a[k][j]%mod))%mod;
tmp.a[i][j] = (tmp.a[i][j]+mod)%mod;
}
}
}
return tmp;
}
matrix cal(matrix res,LL n)
{
matrix tmp;
for(LL i = 0;i < 3;i++) ///构造单位矩阵
for(LL j = 0;j < 3;j++)
if(i == j)
tmp.a[i][j] = 1;
else
tmp.a[i][j] = 0;
while(n) ///二分幂
{
if(n&1)
tmp = mul(tmp,A);
n >>= 1;
A = mul(A,A);
}
return tmp;
}
int main(void)
{
LL T;
scanf("%lld",&T);
while(T--)
{
LL n;
LL a,b,c;
LL f1,f2;
scanf("%lld%lld%lld%lld%lld%lld",&f1,&f2,&a,&b,&c,&n);
if(n == 1)
{
printf("%lld\n",(f1%mod+mod)%mod);
continue;
}
if(n == 2)
{
printf("%lld\n",(f2%mod+mod)%mod);
continue;
}
memset(A.a,0,sizeof A.a);
A.a[0][0] = b;A.a[0][1] = a;A.a[0][2] = 1; ///构造系数矩阵
A.a[1][0] = 1;
A.a[2][2] = 1;
matrix res;
memset(res.a,0,sizeof res.a);
res.a[0][0] = f2; ///初试矩阵
res.a[1][0] = f1;
res.a[2][0] = c;
matrix tmp = cal(res,n-2); ///系数矩阵乘
res = mul(tmp,res); ///再乘初试矩阵输出(0,0)即Fn
printf("%lld\n",res.a[0][0]);
}
return 0;
}