#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 6;
const long long mod = 777777777;
int n, m;
int w[4][4];
struct node {
  long long cnt[4][4];
  node() { memset(cnt, 0, sizeof(cnt)); }
};
node tree[4 * MAXN];
node merge(node n1, node n2) {
  node ret;
  for (int i1 = 1; i1 <= 3; i1++) {
    for (int i2 = 1; i2 <= 3; i2++) {
      for (int j1 = 1; j1 <= 3; j1++) {
        for (int j2 = 1; j2 <= 3; j2++) {
          if (w[j1][i2] == 1)
            ret.cnt[i1][j2] =
                (ret.cnt[i1][j2] + n1.cnt[i1][j1] * n2.cnt[i2][j2]) % mod;
        }
      }
    }
  }
  return ret;
}
void build(int l, int r, int idx) {
  if (l == r) {
    tree[idx].cnt[1][1] = 1;
    tree[idx].cnt[2][2] = 1;
    tree[idx].cnt[3][3] = 1;
    return;
  }
  int mid = (l + r) / 2;
  build(l, mid, idx * 2);
  build(mid + 1, r, idx * 2 + 1);
  tree[idx] = merge(tree[idx * 2], tree[idx * 2 + 1]);
}
void update(int l, int r, int q, int idx, int val) {
  if (l > q) return;
  if (r < q) return;
  if (l == r) {
    if (val == 0) {
      tree[idx] = node();
      tree[idx].cnt[1][1] = 1;
      tree[idx].cnt[2][2] = 1;
      tree[idx].cnt[3][3] = 1;
    } else {
      tree[idx] = node();
      tree[idx].cnt[val][val] = 1;
    }
    return;
  }
  int mid = (l + r) / 2;
  update(l, mid, q, idx * 2, val);
  update(mid + 1, r, q, idx * 2 + 1, val);
  tree[idx] = merge(tree[idx * 2], tree[idx * 2 + 1]);
}
int query() {
  long long ans = 0;
  for (int i = 1; i <= 3; i++) {
    for (int j = 1; j <= 3; j++) {
      ans += tree[1].cnt[i][j];
      ans %= mod;
    }
  }
  return ans;
}
int main() {
  int n, m;
  cin >> n >> m;
  for (int i = 1; i <= 3; i++) {
    for (int j = 1; j <= 3; j++) {
      cin >> w[i][j];
    }
  }
  build(1, n, 1);
  for (int i = 0; i < m; i++) {
    int v, t;
    cin >> v >> t;
    update(1, n, v, 1, t);
    cout << query() << endl;
  }
  return 0;
}
