在正式开始之前,先讲一下看上去没什么意义的矩阵乘法。
对于大小为n*m大小的矩阵A和大小为m*k的矩阵B相乘,答案是一个n*k的矩阵C,满足:
c[i][j]=sum{a[i][l]*b[l][j] | 1<=i<=n,1<=l<=m,1<=j<=k};
typedef struct node { int mat[210][210]; } Matrix; Matrix mul(Matrix a,Matrix b) { Matrix c; memset(c.mat,0x3f,sizeof(c.mat)); for(int k=1; k<=siz; k++) { for(int i=1; i<=siz; i++) { for(int j=1; j<=siz; j++) { c.mat[i][j]+=a.mat[i][k]*b.mat[k][j]; } } } return c; }
这个东西有什么用呢?
*********************************正式开始的分界线************************************
有时递推式又臭又长(主要是时间复杂度,不是长得多恶心),怎么办?
这个时候,就要用一个看似很高能的东西了:递推矩阵。将状态和递推公式转化成矩阵的形式,使得每往后推一步,都相当于让状态矩阵乘一次递推矩阵(<-我瞎编的名),也就是大概这个样子:初始状态*递推矩阵*递推矩阵*……。稍作变换,得到第n步的状态就是:初始状态*(递推矩阵)^n。
现在,只要将 (递推矩阵)^n 快速地算出来就行了。这跟普通的快速幂就没什么区别了。
void pow(int tim) { while(tim) { if(tim&1) ans=mul(ans,tmp); tmp=mul(tmp,tmp); tim>>=1; } }