矩阵快速幂模板例题(快速入门)本来应该提前一个月就掌握这个,但必须考虑硬成牌题再补知识
文章目录矩阵快速幂模板例题(快速入门)模板例题一、HDU 1575:Tr A、POJ 3070:Fibonacci、HNUCM 1620: Fy's dota2
模板
传送门:矩阵的快速幂基础课
如果只是简单地求某矩阵的快速乘幂,那就没什么意义了。 主要是在求出的递归公式数量较大的情况下,使用暴力递归一定会超时。 在那种情况下,矩阵的高速幂的作用完美地体现出来
根据个人码风格和编码习惯,敲了模板。 如果觉得有用,zsdyb可以留下赞歌((手动滑稽) )。
/* *矩阵快速幂n*n矩阵的x次幂*/# include cstdio # include iostream # include cstring # definelllonglong # define mod 9973用户界面优化id 常数上限=15; 结构mat { ll m [ maxn ] [ maxn ]; mat () memset(m,0,sizeof(m ) ) m ); //重载矩阵乘法matoperator*(constmatb ) const ) matans; for(intI=1; i=n; I ) for(intj=1; j=n; j ) for(intk=1; k=n; k ) { ans.m[i][j]=m[i][k]*b.m[k][j]; ans.m[i][j]%=mod; } }返回ans; }; //矩阵的快速幂乘matpow_mat(mata,int b ) ) {mat ans; //初始化为单位矩阵for (inti=1; i=n; I ) { ans.m[i][i]=1; (while ) b ) if ) B1 ) { ans=ans*a; } a=a*a; b=1; }返回Ans; (}int main ) ) { int t; 扫描(' % d ',t ); wile(t-- ) scanf ) ' %d%d ),n,x ); mat a; for(intI=1; i=n; I ) for(intj=1; j=n; j ) Scanf('%lld ',a.m[i][j]; }a=pow_mat(a,x ); //输出矩阵//*for(intI=1; i=n; I ) for(intj=1; j=n; j({couta.m[I][j] '; } coutendl; }*/ll sum=0; for(intI=1; i=n; I ) sum=(suma.m[I][I] ) %mod; }printf('%lld(n )、sum ); }返回0; 例题一、HDU 1575:Tr A主题链接
题目大意:
题意也很简单,只是模板问题; 求某矩阵a的k次幂,然后求矩阵对角线之和取模型
代码:
我的模板正好是解决这个问题的完整代码
二、POJ 3070:Fibonacci主题链接
题目大意:
求出最经典的斐波拉契数列f[n],但由于n较大,如果直接使用递归会超时,但如果选择保存为数组,内存一定会超限。 (因为n太大) ) ) ) ) ) ) ) ) )。
此时,行列为代码:
# include cstdio # include cstring # include iostream # include algorithm # include cstring # define INF0x 3f # define mod 1000 cont 常数int maxn=5; ll n,x; 结构mat { ll m [ maxn ] [ maxn ]; mat () memset(m,0,sizeof(m ) ) m ); } mat操作器* (constmatb ) const ) matans; for(intI=1; i=n; I ) for(intj=1; j=n; j ) for(intk=1; k=n; k ) { ans.m[i][j]=m[i][k]*b.m[k][j]; ans.m[i][j]%=mod; } }返回ans; }; matpow_mat(mata,int b ) { mat ans; for(intI=1; i=n; I ) { ans.m[i][i]=1; (while ) b ) if ) B1 ) { ans=ans*a; } a=a*a; b=1; }返回Ans; (}int main ) ) n=2; while(~scanf('%lld ',x ) ) if ) x==-1 ) break; mat a; a.m[1][1]=1,a.m[1][2]=1; a.m[2][1]=1,a.m[2][2]=0; a=pow_mat(a,x ); printf('%lld(n ),a.m[1][2]; }返回0; (三、hnu cm 16203360 fy’s dota 2主题链接
题目大意:
很明显,我们得到了递归公式:
求的数列下标很大,所以用高速乘方进行矩阵代码:
# include bits/stdc.h # define INF0x 3f 3f # define mod 777777 # definelllonglongusingnamespacestd; 常数双精度EPS=1e-6; 常数上限=15; int n,x; 结构mat { ll m [ maxn ] [ maxn ]; mat () memset(m,0,sizeof(m ) ) m ); //重载矩阵乘法matoperator*(constmatb ) const ) matans; for(intI=1; i=n; I ) for(intj=1; j=n; j ) for(intk=1; k=n; k ) { ans.m[i][j]=m[i][k]*b.m[k][j]; ans.m[i][j]%=mod; } }返回ans; }; //矩阵的快速幂乘matpow_mat(mata,int b ) ) { mat ans; for(intI=1; i=n; I ) ) ans.m(1) ) I )=pow )、n-i ); (while ) b ) if ) B1 ) { ans=ans*a; } a=a*a; b=1; }返回Ans; (}int main ) ) Scanf ) ' %d%d ',n,x ); if(n=x ) ) printf('%d(n ),) int (pow ) 2,x-1 ); } else{ mat a; for(intI=1; i=n; I ) a.m(I ) )1)=1; a.m[i][i 1]=1; }a=pow_mat(a,x-n ); printf('%lld(n ),a.m[1][1]; }返回0; }