引用某位大佬的语句
固定由一些项推出一些项的多维递推可以考虑矩阵快速幂。
这道题,由n-1的好多项,推出n的好多项,所以考虑矩阵快速幂。
而类似于斐波那契数列等应用也可以用矩阵快速幂
模板:
const int N=10;
int n,mod;
int temp[N][N];
int res[N][N],a[N][N];
void mul(int a[][N],int b[][N])//矩阵乘法
{
memset(temp,0,sizeof(temp));
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
for(int k=0;k<N;k++)
temp[i][j]=(temp[i][j]+a[i][k]*b[k][j]%mod)%mod;
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
a[i][j]=temp[i][j];
return ;
}
void fun(int nn)//快速幂,只不过底数换成了矩阵
{
memset(res,0,sizeof(res));
for(int i=0;i<N;i++)
res[i][i]=1;//单位阵
while(nn){
if(nn&1)//奇数的话res×a
mul(res,a);
mul(a,a);//a自己平方
nn>>=1;//幂次/2
}
return ;
}
肉/鱼/巧 代表1/2/3
最后两位:(1,1)代表最后两小时吃肉。。。
0--->11,1--->12,2--->13
3--->21,4--->22,5--->23
6--->31,7--->32,8--->33
初始矩阵
111111111
000000000
000000000
000000000
000000000
000000000
000000000
000000000
000000000
意思是初始为
(1,1)个数=1
(1,2)个数=1
。。。
(3,3)个数=1
变换矩阵为
011000000
000111000
000000101
111000000
000101000
000000011
110000000
000110000
000000110
(0,0)=0:
不能由0推到1
不能由(0,0)推到(0,0),
不能由最后两个小时吃肉+肉
变成最后三个小时吃肉+肉+肉
以此类推
所以每矩阵相乘一次,代表原来的能变化多少次
思想懂了,下面是copy的代码
#include<cstring>
#include<iostream>
#include<cstdio>
using namespace std;
#define ll long long
#define mod 1000000007
int k;
int dim=9;//矩阵维数
struct matirx//注意矩阵的大小
{
ll ma[20][20];
};
matirx mutimatirx(matirx a,matirx b)//矩阵乘
{
matirx t;
memset(t.ma,0,sizeof(t.ma));
for(int i=0; i<dim; i++)
{
for(int k=0; k<dim; k++)
{
for(int j=0; j<dim; j++)
{
t.ma[i][j]+=a.ma[i][k]*b.ma[k][j];
t.ma[i][j]%=mod;//注意要不要取模
}
}
}
return t;
}
matirx powmatirx(matirx a,long long b)//矩阵快速幂
//返回矩阵a的b次方
{
matirx t;
memset(t.ma,0,sizeof(t.ma));
for(int i=0; i<dim; i++)
t.ma[0][i]=1;
while(b)
{
if(b&1)
{
t=mutimatirx(t,a);
}
a=mutimatirx(a,a);
b>>=1;
}
return t;
}
int main()
{
//freopen("input.txt","r",stdin);
int T;
cin>>T;
ll n;
while(T--)
{
cin>>n;
if(n==1)
{
cout<<3<<endl;
continue;
}
matirx res;
memset(res.ma,0,sizeof(res.ma));
res.ma[0][1]=1;res.ma[0][2]=1;
res.ma[1][3]=1;res.ma[1][4]=1;res.ma[1][5]=1;
res.ma[2][6]=1;res.ma[2][8]=1;
res.ma[3][0]=1;res.ma[3][1]=1;res.ma[3][2]=1;
res.ma[4][3]=1;res.ma[4][5]=1;
res.ma[5][7]=1;res.ma[5][8]=1;
res.ma[6][0]=1;res.ma[6][1]=1;
res.ma[7][3]=1;res.ma[7][4]=1;
res.ma[8][6]=1;res.ma[8][7]=1;
res=powmatirx(res,n-2);//求res矩阵的n次幂
ll ans=0;
for(int i=0;i<9;++i)
{
ans+=res.ma[0][i];
ans%=mod;
}
cout<<ans<<endl;
}
return 0;
}