POJ3735【矩阵快速幂】
逛了一圈。。。觉得这篇讲的比较清楚:传送门~
简要概括:
1、线性代数的知识,单位矩阵的利用;(如果不知道单位矩阵的,先去补习一下线代,做几题行列式就会了);
2、然后构造好矩阵以后,直接做M次乘积运算,然后利用一个[1, 0 , ... , 0 ]矩阵提取答案就好了,对,那个[1,0,..., 0 ] 就是获取答案的作用。
PS
以前的矩阵快速幂总是这样写的:先构造一个矩阵,然后跑一发矩阵快速幂,然后这个矩阵a乘以另一个矩阵b就会得出答案,而答案矩阵往往会包括前一个答案的值。所以自己就有点不知所措。【这里写自己的智障困惑。。】
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; typedef long long LL; struct asd{ LL a[110][110]; }; int n; asd mul(asd a, asd b) { asd ans; memset(ans.a,0,sizeof(ans.a)); for(int k=0;k<=n;k++) for(int i=0;i<=n;i++) if(a.a[i][k]) for(int j=0;j<=n;j++) ans.a[i][j]+=a.a[i][k]*b.a[k][j]; return ans; } asd quickmul(int g,asd x) { asd ans; memset(ans.a,0,sizeof(ans.a)); for(int i=0;i<=n;i++) ans.a[i][i]=1; while(g) { if(g&1) ans=mul(ans,x); x=mul(x,x); g>>=1; } return ans; } asd init(int k) { asd tmp; memset(tmp.a,0,sizeof(tmp.a)); for(int i=0;i<=n;++i) tmp.a[i][i]=1; char x[5]; int a,b; while(k--) { scanf("%s",x); if(x[0]=='g') { scanf("%d",&a); tmp.a[0][a]++; } else if(x[0]=='s') { scanf("%d%d",&a,&b); for(int i=0;i<=n;i++) swap(tmp.a[i][a],tmp.a[i][b]); } else { scanf("%d",&a); for(int i=0;i<=n;i++) tmp.a[i][a]=0; } } return tmp; } int main() { int m,k; asd ans,tmp; while(~scanf("%d%d%d",&n,&m,&k)) { if((!n)&&(!m)&&(!k)) break; tmp=init(k); ans=quickmul(m,tmp); memset(tmp.a,0,sizeof(tmp.a)); tmp.a[0][0]=1; ans=mul(tmp,ans); for(int i=1;i<=n;i++) { if(i!=1) printf(" "); printf("%lld",ans.a[0][i]); } puts(""); } return 0; }