3233:Matrix Power Series
概要
行列A(30*30以下)とk(<10^9)とm(<10^4)が与えられる。S=A+A^2+…+A^kをmod mで求める問題。
kが大きいのでO(log k)は必須。まさか公式一発ということもないだろう。そう考えると分割統治の発見は容易で、{A+…+A^(k/2)} + A^(k/2){A+…+A^(k/2)}で求まりそう。分割統治はなかなか書けないからちょっと嬉しかった。手元で最大ケースだと1.8秒くらいで、制限時間は3秒だから多分大丈夫だと思ってsubmitしたらTLE。行列を全部参照渡しに書き直して再送信したら無事ACがとれた。
#define matrix vector< vector<int> > int n, m; matrix a(30, vector<int>(30,0)), e(30, vector<int>(30,0)); inline matrix prod(matrix &x, matrix &y){ matrix ret(30, vector<int>(30,0)); int i, j, k; REP(i,n)REP(j,n)REP(k,n) ret[i][j] += x[i][k]*y[k][j]%m; REP(i,n)REP(j,n) ret[i][j] %= m; return ret; } inline matrix add(matrix &x, matrix &y){ int i,j; vector<vector<int> > ret(30, vector<int>(30,0)); REP(i,n)REP(j,n) ret[i][j] = (x[i][j] + y[i][j])%m; return ret; } inline matrix power(int k, matrix &x){ if(k==1) return x; if(k&1){ matrix t1 = power(k-1,x); return prod(x, t1); } matrix y = prod(x,x); return power(k/2, y); } inline matrix solve(int k){ if(k==1) return a; matrix t1 = solve(k/2), t2 = power(k/2,a); t2 = add(e,t2); matrix ret = prod(t1, t2); if(k&1){ t1 = power(k,a); ret = add(ret, t1); } return ret; } int main(){ int k, i, j; scanf("%d%d%d",&n,&k,&m); REP(i,n)REP(j,n){ if(i==j) e[i][j] = 1; scanf("%d",&a[i][j]); } matrix ans = solve(k); REP(i,n){ REP(j,n){ printf("%d",ans[i][j]%m); if(j==n-1)printf("\n"); else printf(" "); } } return 0; }