← Home
```go
package main

import (
	"fmt"
	"sort"
)

const MOD = 998244353

type SegTree struct {
	tree    []int64
	lazy    []int64
	hasLazy []bool
	n       int
	mod     int64
}

func NewSegTree(nn int, mmod int64) *SegTree {
	return &SegTree{
		tree:    make([]int64, 4*(nn+1)),
		lazy:    make([]int64, 4*(nn+1)),
		hasLazy: make([]bool, 4*(nn+1)),
		n:       nn,
		mod:     mmod,
	}
}

func (s *SegTree) push(node, start, end int) {
	if s.hasLazy[node] {
		s.tree[node] = int64(end-start+1) * s.lazy[node] % s.mod
		if start != end {
			s.lazy[2*node] = s.lazy[node]
			s.hasLazy[2*node] = true
			s.lazy[2*node+1] = s.lazy[node]
			s.hasLazy[2*node+1] = true
		}
		s.hasLazy[node] = false
	}
}

func (s *SegTree) updateRange(node, start, end, l, r int, val int64) {
	s.push(node, start, end)
	if start > end || start > r || end < l {
		return
	}
	if l <= start && end <= r {
		s.lazy[node] = val
		s.hasLazy[node] = true
		s.push(node, start, end)
		return
	}
	mid := (start + end) / 2
	s.updateRange(2*node, start, mid, l, r, val)
	s.updateRange(2*node+1, mid+1, end, l, r, val)
	s.tree[node] = (s.tree[2*node] + s.tree[2*node+1]) % s.mod
}

func (s *SegTree) updatePoint(node, start, end, idx int, val int64) {
	s.push(node, start, end)
	if start > end || start > idx || end < idx {
		return
	}
	if start == end {
		s.tree[node] = val % s.mod
		return
	}
	mid := (start + end) / 2
	if idx <= mid {
		s.updatePoint(2*node, start, mid, idx, val)
	} else {
		s.updatePoint(2*node+1, mid+1, end, idx, val)
	}
	s.tree[node] = (s.tree[2*node] + s.tree[2*node+1]) % s.mod
}

func (s *SegTree) getQuery(node, start, end, l, r int) int64 {
	s.push(node, start, end)
	if start > end || start > r || end < l {
		return 0
	}
	if l <= start && end <= r {
		return s.tree[node]
	}
	mid := (start + end) / 2
	return (s.getQuery(2*node, start, mid, l, r) + s.getQuery(2*node+1, mid+1, end, l, r)) % s.mod
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func main() {
	var n, k, m int
	fmt.Scan(&n, &k, &m)
	ls := make([]int, m)
	rs := make([]int, m)
	xs := make([]int, m)
	for i := 0; i < m; i++ {
		fmt.Scan(&ls[i], &rs[i], &xs[i])
	}
	ans := int64(1)
	for bit := 0; bit < k; bit++ {
		diff := make([]int, n+2)
		for j := 0; j < m; j++ {
			if (xs[j] & (1 << bit)) != 0 {
				diff[ls[j]]++
				diff[rs[j]+1]--
			}
		}
		forced1 := make([]bool, n+2)
		pre := 0
		for i := 1; i <= n; i++ {
			pre += diff[i]
			forced1[i] = pre > 0
		}
		var free_pos []int
		for i := 1; i <= n; i++ {
			if !forced1[i] {
				free_pos = append(free_pos, i)
			}
		}
		qq := len(free_pos)
		var force0 [][2]int
		for j := 0; j < m; j++ {
			if (xs[j] & (1 << bit)) == 0 {
				force0 = append(force0, [2]int{ls[j], rs[j]})
			}
		}
		possible := true
		for _, seg := range force0 {
			ll := seg[0]
			rr := seg[1]
			it := sort.Search(len(free_pos), func(k int) bool { return free_pos[k] >= ll })
			if it < len(free_pos) && free_pos[it] <= rr {
				continue
			}
			possible = false
			break
		}
		var ways int64
		if possible {
			st := NewSegTree(qq, MOD)
			st.updatePoint(1, 0, qq, 0, 1)
			maxSt := make([]int, qq+2)
			for _, seg := range force0 {
				ll := seg[0]
				rr := seg[1]
				itlow := sort.Search(len(free_pos), func(k int) bool { return free_pos[k] >= ll })
				if itlow >= len(free_pos) || free_pos[itlow] > rr {
					continue
				}
				ithigh := sort.Search(len(free_pos), func(k int) bool { return free_pos[k] > rr }) - 1
				left_idx := itlow + 1
				right_idx := ithigh + 1
				if left_idx > right_idx {
					continue
				}
				maxSt[right_idx] = max(maxSt[right_idx], left_idx)
			}
			for ii := 1; ii <= qq; ii++ {
				pp := maxSt[ii]
				total_prev := st.getQuery(1, 0, qq, 0, ii-1)
				st.updateRange(1, 0, qq, 0, pp-1, 0)
				st.updatePoint(1, 0, qq, ii, total_prev)
			}
			ways = st.getQuery(1, 0, qq, 0, qq)
		}
		ans = (ans * ways) % MOD
	}
	fmt.Println(ans)
}
```