土下座しながら探索中

主に競技プログラミング

AOJ 1327 : One-Dimensional Cellular Automaton

問題リンク:One-Dimensional Cellular Automaton | Aizu Online Judge

解法:
行列におとして計算した

N = 5 T = 1の場合、与えられた式を行列で表すと次の様になる

[ S(0,1) ]   [ S(-1,0) S(0,0) S(1,0) ] [A]
[ S(1,1) ]   [ S(0, 0) S(1,0) S(2,0) ] [ ]
[ S(2,1) ] = [ S(1, 0) S(2,0) S(3,0) ] [B]
[ S(3,1) ]   [ S(2, 0) S(3,0) S(4,0) ] [ ]
[ S(4,1) ]   [ S(3, 0) S(4,0) S(5,0) ] [C]

これを次の様に変える

[ S(0,1) ]   [ B C 0 0 0 ] [ S(0,0) ]
[ S(1,1) ]   [ A B C 0 0 ] [ S(1,0) ]
[ S(2,1) ] = [ 0 A B C 0 ] [ S(2,0) ]
[ S(3,1) ]   [ 0 0 A B C ] [ S(3,0) ]
[ S(4,1) ]   [ 0 0 0 A B ] [ S(4,0) ]


同様に、 N = 5 T = 2 の場合、

[ S(0,2) ]   [ S(-1,1) S(0,1) S(1,1) ] [A]
[ S(1,2) ]   [ S(0, 1) S(1,1) S(2,1) ] [ ]
[ S(2,2) ] = [ S(1, 1) S(2,1) S(3,1) ] [B]
[ S(3,2) ]   [ S(2, 1) S(3,1) S(4,1) ] [ ]
[ S(4,2) ]   [ S(3, 1) S(4,1) S(5,1) ] [C]

       |
       V

[ S(0,2) ]   [ B C 0 0 0 ] [ S(0,1) ]
[ S(1,2) ]   [ A B C 0 0 ] [ S(1,1) ]
[ S(2,2) ] = [ 0 A B C 0 ] [ S(2,1) ]
[ S(3,2) ]   [ 0 0 A B C ] [ S(3,1) ]
[ S(4,2) ]   [ 0 0 0 A B ] [ S(4,1) ]
    
       |
       V

[ S(0,2) ]   [ B C 0 0 0 ] [ B C 0 0 0 ] [ S(0,0) ]
[ S(1,2) ]   [ A B C 0 0 ] [ A B C 0 0 ] [ S(1,0) ]
[ S(2,2) ] = [ 0 A B C 0 ] [ 0 A B C 0 ] [ S(2,0) ]
[ S(3,2) ]   [ 0 0 A B C ] [ 0 0 A B C ] [ S(3,0) ]
[ S(4,2) ]   [ 0 0 0 A B ] [ 0 0 0 A B ] [ S(4,0) ]


といった風に求めたい行列S(0..N-1,T)はS(0..N-1,0)に
[ B C 0 0 0 ]
[ A B C 0 0 ]
[ 0 A B C 0 ] のT乗を掛けたものになる
[ 0 0 A B C ]
[ 0 0 0 A B ] 

T乗をT回ループを回してやるとTLEになるので
繰り返し二乗法を使う

コード:

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vvi matrix;

int N,M,A,B,C,T;

void init(matrix &mat)
{

  mat[N-1][N-2]             = A;
  mat[0][0] = mat[N-1][N-1] = B;
  mat[0][1]                 = C;
  REP(i,1,N-1)
    {
      mat[i][i-1] = A;
      mat[i][i] = B;
      mat[i][i+1] = C;
    }
}

/*
pow,multiは行列のべき乗と掛け算
*/

int main()
{
  while(cin >> N >> M >> A >> B >> C >> T,N|M|A|B|C|T)
    {
      matrix s(N,vi(1));
      rep(i,N)cin >> s[i][0];
      matrix coef(N,vi(N,0));
      init(coef);
      coef = pow(coef,T);
      s = multi(coef,s);
      rep(i,N)cout << (i?" ":"") << s[i][0];
      cout << endl;
    }
  return 0;
}