← Home
```go
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"sort"
)

const MOD int64 = 998244353

type FastScanner struct {
	data []byte
	idx  int
}

func NewFastScanner() *FastScanner {
	data, _ := io.ReadAll(os.Stdin)
	return &FastScanner{data: data}
}

func (fs *FastScanner) NextInt64() int64 {
	n := len(fs.data)
	for fs.idx < n {
		b := fs.data[fs.idx]
		if (b >= '0' && b <= '9') || b == '-' {
			break
		}
		fs.idx++
	}
	sign := int64(1)
	if fs.data[fs.idx] == '-' {
		sign = -1
		fs.idx++
	}
	var v int64
	for fs.idx < n {
		b := fs.data[fs.idx]
		if b < '0' || b > '9' {
			break
		}
		v = v*10 + int64(b-'0')
		fs.idx++
	}
	return sign * v
}

type Cell struct {
	y int64
	c int
}

var g2FromColor [3]int
var g3FromG2Color [4][3]int
var map64toR [64]int
var nextComp [3][]int
var firstSG []int
var powMats [][]int64
var R int

func mexMask(mask int) int {
	if mask&1 == 0 {
		return 0
	}
	if mask&2 == 0 {
		return 1
	}
	if mask&4 == 0 {
		return 2
	}
	return 3
}

func matMul(a, b []int64) []int64 {
	c := make([]int64, R*R)
	for i := 0; i < R; i++ {
		rowC := c[i*R : (i+1)*R]
		rowA := a[i*R : (i+1)*R]
		for k := 0; k < R; k++ {
			av := rowA[k]
			if av == 0 {
				continue
			}
			rowB := b[k*R : (k+1)*R]
			for j := 0; j < R; j++ {
				bv := rowB[j]
				if bv == 0 {
					continue
				}
				rowC[j] = (rowC[j] + av*bv) % MOD
			}
		}
	}
	return c
}

func mulVecMat(src, mat, dst []int64) {
	for i := 0; i < R; i++ {
		dst[i] = 0
	}
	for i := 0; i < R; i++ {
		sv := src[i]
		if sv == 0 {
			continue
		}
		row := mat[i*R : (i+1)*R]
		for j := 0; j < R; j++ {
			mv := row[j]
			if mv == 0 {
				continue
			}
			dst[j] = (dst[j] + sv*mv) % MOD
		}
	}
}

func applyPower(vec, buf []int64, l int64) ([]int64, []int64) {
	bit := 0
	for l > 0 {
		if l&1 == 1 {
			mulVecMat(vec, powMats[bit], buf)
			vec, buf = buf, vec
		}
		l >>= 1
		bit++
	}
	return vec, buf
}

func computeSmallCounts(length int64, cells []Cell) [4]int64 {
	fixed := [3]int{-1, -1, -1}
	for _, cell := range cells {
		fixed[int(cell.y)-1] = cell.c
	}
	var res [4]int64
	for c1 := 0; c1 < 3; c1++ {
		if fixed[0] != -1 && fixed[0] != c1 {
			continue
		}
		if length == 1 {
			res[0]++
			continue
		}
		for c2 := 0; c2 < 3; c2++ {
			if fixed[1] != -1 && fixed[1] != c2 {
				continue
			}
			g2 := g2FromColor[c2]
			if length == 2 {
				res[g2]++
				continue
			}
			for c3 := 0; c3 < 3; c3++ {
				if fixed[2] != -1 && fixed[2] != c3 {
					continue
				}
				g3 := g3FromG2Color[g2][c3]
				res[g3]++
			}
		}
	}
	return res
}

func computeStripCounts(length int64, cells []Cell) [4]int64 {
	if length <= 3 {
		return computeSmallCounts(length, cells)
	}

	fixed := [3]int{-1, -1, -1}
	idx := 0
	for idx < len(cells) && cells[idx].y <= 3 {
		fixed[int(cells[idx].y)-1] = cells[idx].c
		idx++
	}

	vec := make([]int64, R)
	buf := make([]int64, R)

	for c1 := 0; c1 < 3; c1++ {
		if fixed[0] != -1 && fixed[0] != c1 {
			continue
		}
		for c2 := 0; c2 < 3; c2++ {
			if fixed[1] != -1 && fixed[1] != c2 {
				continue
			}
			g2 := g2FromColor[c2]
			for c3 := 0; c3 < 3; c3++ {
				if fixed[2] != -1 && fixed[2] != c3 {
					continue
				}
				g3 := g3FromG2Color[g2][c3]
				s := (g3 << 4) | (g2 << 2)
				r := map64toR[s]
				vec[r]++
			}
		}
	}

	pos := int64(3)

	for ; idx < len(cells); idx++ {
		p := cells[idx].y
		if p > pos+1 {
			vec, buf = applyPower(vec, buf, p-1-pos)
		}

		for i := 0; i < R; i++ {
			buf[i] = 0
		}
		ns := nextComp[cells[idx].c]
		for s := 0; s < R; s++ {
			sv := vec[s]
			if sv == 0 {
				continue
			}
			t := ns[s]
			buf[t] += sv
			if buf[t] >= MOD {
				buf[t] -= MOD
			}
		}
		vec, buf = buf, vec
		pos = p
	}

	if pos < length {
		vec, buf = applyPower(vec, buf, length-pos)
	}

	var res [4]int64
	for i := 0; i < R; i++ {
		sv := vec[i]
		if sv == 0 {
			continue
		}
		g := firstSG[i]
		res[g] += sv
		if res[g] >= MOD {
			res[g] -= MOD
		}
	}
	return res
}

func main() {
	fs := NewFastScanner()

	n := int(fs.NextInt64())
	a := make([]int64, n)
	var maxFree int64
	for i := 0; i < n; i++ {
		a[i] = fs.NextInt64()
		if a[i] > 3 && a[i]-3 > maxFree {
			maxFree = a[i] - 3
		}
	}

	m := int(fs.NextInt64())
	pre := make([][]Cell, n)
	for i := 0; i < m; i++ {
		x := int(fs.NextInt64()) - 1
		y := fs.NextInt64()
		c := int(fs.NextInt64()) - 1
		pre[x] = append(pre[x], Cell{y: y, c: c})
	}

	var f [3][3]int
	for i := 0; i < 3; i++ {
		for j := 0; j < 3; j++ {
			f[i][j] = int(fs.NextInt64())
		}
	}

	for i := 0; i < n; i++ {
		if len(pre[i]) > 1 {
			cells := pre[i]
			sort.Slice(cells, func(a, b int) bool {
				return cells[a].y < cells[b].y
			})
		}
	}

	for c := 0; c < 3; c++ {
		mask := 0
		if f[c][0] == 1 {
			mask |= 1
		}
		g2FromColor[c] = mexMask(mask)
	}

	for g2 := 0; g2 < 4; g2++ {
		for c := 0; c < 3; c++ {
			mask := 0
			if f[c][0] == 1 {
				mask |= 1 << g2
			}
			if f[c][1] == 1 {
				mask |= 1
			}
			g3FromG2Color[g2][c] = mexMask(mask)
		}
	}

	var next64 [3][64]int
	for s := 0; s < 64; s++ {
		u := (s >> 4) & 3
		v := (s >> 2) & 3
		w := s & 3
		for c := 0; c < 3; c++ {
			mask := 0
			if f[c][0] == 1 {
				mask |= 1 << u
			}
			if f[c][1] == 1 {
				mask |= 1 << v
			}
			if f[c][2] == 1 {
				mask |= 1 << w
			}
			g := mexMask(mask)
			next64[c][s] = (g << 4) | (u << 2) | v
		}
	}

	var vis [64]bool
	queue := make([]int, 0, 64)
	for c2 := 0; c2 < 3; c2++ {
		g2 := g2FromColor[c2]
		for c3 := 0; c3 < 3; c3++ {
			g3 := g3FromG2Color[g2][c3]
			s := (g3 << 4) | (g2 << 2)
			if !vis[s] {
				vis[s] = true
				queue = append(queue, s)
			}
		}
	}
	for head := 0; head < len(queue); head++ {
		s := queue[head]
		for c := 0; c < 3; c++ {
			t := next64[c][s]
			if !vis[t] {
				vis[t] = true
				queue = append(queue, t)
			}
		}
	}

	R = len(queue)
	for i := 0; i < 64; i++ {
		map64toR[i] = -1
	}
	for i, s := range queue {
		map64toR[s] = i
	}

	firstSG = make([]int, R)
	for c := 0; c < 3; c++ {
		nextComp[c] = make([]int, R)
	}
	base := make([]int64, R*R)
	for i, s := range queue {
		firstSG[i] = (s >> 4) & 3
		for c := 0; c < 3; c++ {
			t := map64toR[next64[c][s]]
			nextComp[c][i] = t
			base[i*R+t]++
		}
	}

	bits := 1
	for (int64(1) << bits) <= maxFree {
		bits++
	}
	powMats = make([][]int64, bits)
	powMats[0] = base
	for i := 1; i < bits; i++ {
		powMats[i] = matMul(powMats[i-1], powMats[i-1])
	}

	dp := [4]int64{1, 0, 0, 0}
	for i := 0; i < n; i++ {
		cnt := computeStripCounts(a[i], pre[i])
		var ndp [4]int64
		for x := 0; x < 4; x++ {
			if dp[x] == 0 {
				continue
			}
			for g := 0; g < 4; g++ {
				if cnt[g] == 0 {
					continue
				}
				ndp[x^g] = (ndp[x^g] + dp[x]*cnt[g]) % MOD
			}
		}
		dp = ndp
	}

	out := bufio.NewWriterSize(os.Stdout, 1<<20)
	fmt.Fprintln(out, dp[0])
	out.Flush()
}
```