矩阵快速幂总结
基础:快速幂,矩阵乘法;
快速幂:
#include<cstdio> #include<cstring> #define ll long long ll poww(ll a,ll b) { ll ans=1; while(b) { if(b&1) ans*=a; b>>=1;a*=a; } return ans; } int main() { ll a,b; scanf("%lld %lld",&a,&b); ll ans=poww(a,b); printf("%lld",ans); return 0; }
矩阵乘法:
#include<cstdio> #include<cstring> const int N=112; int m1[N][N],m2[N][N]; int main() { int n; scanf("%d",&n); for(int t=1;t<=2;t++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(t==1) scanf("%d",&m1[i][j]); else scanf("%d",&m2[i][j]); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { int ans=0; for(int k=1;k<=n;k++) { ans+=m1[i][k]*m2[k][j]; } printf("%d ",ans); } printf("\n"); } return 0; }
矩阵快速幂:
将二者结合就是矩阵快速幂;
#include<cstdio> #include<cstring> const int N=112; int res[N][N],tt[N][N]; int n,m; const int mod=1e9+7; inline void matrix(int a[N][N],int b[N][N]) { memset(tt,0,sizeof(tt)); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) for(int k=1;k<=n;k++) tt[i][j]=( tt[i][j]+(long long)a[i][k]*b[k][j]%mod)%mod; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) a[i][j]=tt[i][j]; } int a[N][N]; void j_poww(int b) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&a[i][j]); memset(res,0,sizeof(res)); for(int i=1;i<=n;i++) res[i][i]=1; while(b) { if(b&1) matrix(res,a); b>>=1; matrix(a,a) ; } } int main() { scanf("%d %d",&n,&m); j_poww(m); for(int i=1;i<=n;i++,printf("\n")) for(int j=1;j<=n;j++) printf("%d ",res[i][j]); return 0; }
运用:
一:51nod 1013 3的幂的和可以用矩乘(也可以用公式)
二:vijos Warcraft III 守望者的烦恼:矩乘
#include<cstdio> #include<cstring> #define ll long long const int N=12,mod=7777777; int k,n; ll f[N]; int min(int a,int b) { if(a>b) return b; else return a; } typedef long long matrix [N][N]; inline void calc(matrix a,matrix b) { matrix c; memset(c,0,sizeof(c)); for(int i=1;i<=k;i++) for(int j=1;j<=k;j++) for(int l=1;l<=k;l++) c[i][j]=(c[i][j]+a[i][l]*b[l][j])%mod; for(int i=1;i<=k;i++) for(int j=1;j<=k;j++) a[i][j]=c[i][j]; } matrix ans,a; long long b[N]; ll poww(int n) { for(int i=1;i<=k;i++) ans[i][i]=1; for(int i=2;i<=k;i++) a[i-1][i]=1; for(int i=1;i<=k;i++) a[k][i]=1; for(int i=k;i>=1;i--) b[k-i+1]=f[k+1-i]; // for(int i=1;i<=k;i++) b[i]=f[i-1]; while(n) { if(n&1) calc(ans,a); n>>=1; calc(a,a); } ll sum=0; for(int i=1;i<=k;i++) sum=(sum+ans[k][i]*b[i]%mod)%mod; return sum; } int main() { scanf("%d %d",&k,&n); f[0]=1; for(int i=1;i<=k;i++) { for(int j=1;j<=i;j++) f[i]=(f[i]+f[i-j])%mod; } // for(int i=1;i<=10;i++) printf("%d ",f[i]); if(n<=k) printf("%lld",f[n]); else printf("%lld",poww(n-k)); return 0; }
总结:
基础与代码都不难,关键是构建矩阵(多做点题)