#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using uint = unsigned int; using ll = long long; using ull = unsigned long long; template constexpr T TEN(int n) {return (n==0)?1:10*TEN(n-1);} int bsr(int x) { return 31 - __builtin_clz(x); } /** * 行列ライブラリ */ template struct Matrix { vector> d; int N, M; Matrix(int N, int M) : N(N), M(M) { d.resize(N); for (int i = 0; i < N; i++) { d[i] = vector(M); } } static Matrix One(int N) { Matrix r(N, N); for (int i = 0; i < N; i++) { r.d[i][i] = D(1); } return r; } vector& operator[](int p) {return d[p];} const vector& operator[](int p) const {return d[p];} const Matrix operator+(const Matrix &right) const { assert(right.N == N && right.M == M); Matrix res(N, M); for (int i = 0; i < N; i++) { for (int j = 0; j < M; j++) { res[i][j] = d[i][j]+right[i][j]; } } return res; } const Matrix operator*(const Matrix &right) const { assert(M == right.N); Matrix res(N, right.M), r(right.M, right.N); for (int i = 0; i < right.M; i++) { for (int j = 0; j < right.N; j++) { r[i][j] = right[j][i]; } } for (int i = 0; i < N; i++) { for (int j = 0; j < right.M; j++) { for (int k = 0; k < M; k++) { res[i][j] += d[i][k]*r[j][k]; } } } return res; } const Matrix operator*(const D &x) const { Matrix res(N, M); for (int i = 0; i < N; i++) { for (int j = 0; j < M; j++) { res[i][j] = d[i][j]*x; } } return res; } }; template Matrix pow(Matrix x, ll p) { assert(x.N == x.M); int N = x.N; Matrix res(N, N), buf = x; for (int i = 0; i < N; i++) res[i][i] = T(1); while(p != 0) { if (p % 2) { res = res*buf; } p /= 2; buf = buf*buf; } return res; } template struct ModInt { uint v; ModInt() : v{0} {} ModInt(ll v) : v{normS(v%MD+MD)} {} static uint normS(const uint &x) {return (x; template struct SegTree { int lg, sz; vector n; SegTree(int sz) { lg = bsr(2*sz-1); sz = 1<sz = sz; n = vector(2*sz); for (int i = 2*sz-1; i >= sz; i--) { n[i].init(i-sz); } for (int i = sz-1; i >= 1; i--) { n[i] = N(n[2*i], n[2*i+1]); } } template Q single(int idx, Q q) { if (idx < 0 or sz <= idx) return q; idx += sz; for (int i = lg; i >= 1; i--) { int k = idx>>i; n[k].push(n[2*k], n[2*k+1]); } q += n[idx]; if (q.update()) { for (int i = 1; i <= lg; i++) { int k = idx>>i; n[k].update(n[2*k], n[2*k+1]); } } return q; } template void query(int a, int b, Q &q, int k, int sz) { if (a <= 0 and sz <= b) { q += n[k]; return; } n[k].push(n[2*k], n[2*k+1]); if (a < sz/2) query(a, b, q, 2*k, sz/2); if (sz/2 < b) query(a-sz/2, b-sz/2, q, 2*k+1, sz/2); if (q.update()) n[k].update(n[2*k], n[2*k+1]); } template Q query(int a, int b, Q q) { if (a < sz and 0 < b) query(a, b, q, 1, sz); return q; } }; using M = Matrix; struct NodeA { using N = NodeA; M da = M::One(3); // a M dab = M(2, 3), dbb = M::One(2); int id; void init() { } void init(int id) { this->id = id; for (int i = 0; i < 2; i++) { for (int j = 0; j < 3; j++) { dab[i][j] = 6*(id+1) + 3*i + j; } } } NodeA() { init(); } NodeA(N &l, N &r) { init(-1); update(l, r); } void update(const N &l, const N &r) { da = r.da * l.da; dab = l.dab + l.dbb * r.dab * l.da; dbb = l.dbb * r.dbb; } void push(N &l, N &r) { } // query struct GetQuery { M da = M::One(3); M dab = M(2, 3); M dbb = M::One(2); static constexpr bool update() { return false; } void operator+=(N &r) { dab = dab + dbb * r.dab * da; dbb = dbb * r.dbb; da = r.da * da; } }; struct SetAQuery { M da = M(3, 3); SetAQuery(M da) : da(da) {} static constexpr bool update() { return true; } void operator+=(N &n) { n.da = da; M dab(2, 3); for (int i = 0; i < 2; i++) { for (int j = 0; j < 3; j++) { dab[i][j] = 6*(n.id+1) + 3*i + j; } } n.dab = dab * da; } }; struct SetBQuery { M db = M(2, 2); SetBQuery(M db) : db(db) {} static constexpr bool update() { return true; } void operator+=(N &n) { n.dbb = db; } }; }; int main() { int n; scanf("%d", &n); M fa(3, 1), fb(2, 1); for (int i = 0; i < 3; i++) { int a; scanf("%d", &a); fa[i][0] = a; } for (int i = 0; i < 2; i++) { int b; scanf("%d", &b); fb[i][0] = b; } SegTree segA(n); int q; scanf("%d", &q); for (int qc = 0; qc < q; qc++) { char buf[3]; scanf(" %s", buf); string s = buf; if (s == "a") { int id; scanf("%d", &id); M na(3, 3); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { int a; scanf("%d", &a); na[i][j] = a; } } segA.single(id, NodeA::SetAQuery(na)); } else if (s == "b") { int id; scanf("%d", &id); id--; M nb(2, 2); for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { int a; scanf("%d", &a); nb[i][j] = a; } } segA.single(id, NodeA::SetBQuery(nb)); } else if (s == "ga") { int id; scanf("%d", &id); auto res = segA.query(0, id, NodeA::GetQuery()).da * fa; for (int i = 0; i < 3; i++) { printf("%d", res[i][0].v); if (i < 3-1) { printf(" "); } else { printf("\n"); } } fflush(stdout); } else if (s == "gb") { int id; scanf("%d", &id); auto aa = segA.query(0, id, NodeA::GetQuery()).da * fa; auto q = segA.query(id, n, NodeA::GetQuery()); auto res = q.dab * aa + q.dbb * fb; for (int i = 0; i < 2; i++) { printf("%d", res[i][0].v); if (i < 2-1) { printf(" "); } else { printf("\n"); } } fflush(stdout); } } return 0; }