矩阵快速幂推导过程:https://blog.csdn.net/u012061345/article/details/52224623
矩阵快速幂求解数列第n项的关键在于计算系数矩阵A。之后就是套模板了。
模板(求解斐波那契数列第n项):
#include
#include
#define LL long long
#define mod 2147493647
using namespace std;
struct mat
{
LL m[2][2];
};
mat operator*(mat x, mat y)
{
mat ret;
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
ret.m[i][j]=0;
for(int k=0;k<2;k++)
ret.m[i][j]=(x.m[i][k]*y.m[k][j]%mod+ret.m[i][j]%mod)%mod;
}
}
return ret;
}
mat pow_mat(mat a,LL n)
{
mat ret;
memset(ret.m,0,sizeof(ret.m));
for(int i=0;i<2;i++)
ret.m[i][i]=1;
while(n)
{
if(n&1)
ret=ret*a;
a=a*a;
n>>=1;
}
return ret;
}
int main()
{
mat A={1,1,1,0};
int t;
while(~scanf("%d",&t))
{
mat x0;
memset(x0.m,0,sizeof(x0.m));
x0.m[0][0]=1;
x0.m[1][0]=1;
x0=pow_mat(A,t-1)*x0;
printf("%lld\n",x0.m[0][0]);
}
return 0;
}
例题:https://cn.vjudge.net/contest/299842#problem/N
题意:
给出数列 F n F_n Fn=2* F n − 2 F_{n-2} Fn−2+ F n − 1 F_{n-1} Fn−1+ n 4 n^4 n4
t组数据,每组给出数列的前两项和一个数n,求数列的第n项。
首先构造系数矩阵:
mat A=
{
1,4,6,4,1,0,0,
0,1,3,3,1,0,0,
0,0,1,2,1,0,0,
0,0,0,1,1,0,0,
0,0,0,0,1,0,0,
0,0,0,0,0,0,1,
1,4,6,4,1,2,1
};
此时, x n − 1 x_{n-1} xn−1=
{
(n-1)^4
(n-1)^3
(n-1)^2
(n-1)^1
(n-1)^0
a
b
};
x n x_n xn=
{
n^4
n^3
n^2
n^1
n^0
a
b
};
满足 x n x_n xn=A x n − 1 x_{n-1} xn−1。
代码:
#include
#include
#define LL long long
#define N 7
#define mod 2147493647
using namespace std;
struct mat
{
LL m[N][N];
};
mat operator*(mat x, mat y)
{
mat ret;
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
{
ret.m[i][j]=0;
for(int k=0;k<N;k++)
ret.m[i][j]=(x.m[i][k]*y.m[k][j]%mod+ret.m[i][j]%mod)%mod;
}
}
return ret;
}
mat pow_mat(mat a,LL n)
{
mat ret;
memset(ret.m,0,sizeof(ret.m));
for(int i=0;i<N;i++)
ret.m[i][i]=1;
while(n)
{
if(n&1)
ret=ret*a;
a=a*a;
n>>=1;
}
return ret;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
LL a,b,n;
scanf("%lld%lld%lld",&n,&a,&b);
if(n==1)
printf("%lld\n",a);
else if(n==2)
printf("%lld\n",b);
else
{
mat x0;
memset(x0.m,0,sizeof(x0.m));
x0.m[0][0]=16;
x0.m[1][0]=8;
x0.m[2][0]=4;
x0.m[3][0]=2;
x0.m[4][0]=1;
x0.m[5][0]=a;
x0.m[6][0]=b;
mat A=
{
1,4,6,4,1,0,0,
0,1,3,3,1,0,0,
0,0,1,2,1,0,0,
0,0,0,1,1,0,0,
0,0,0,0,1,0,0,
0,0,0,0,0,0,1,
1,4,6,4,1,2,1
};
x0=pow_mat(A,n-2)*x0;
printf("%lld\n",x0.m[6][0]);
}
}
return 0;
}