← Home
```go
package main

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

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) nextInt() int {
	n := len(fs.data)
	for fs.idx < n {
		c := fs.data[fs.idx]
		if c >= '0' && c <= '9' {
			break
		}
		fs.idx++
	}
	val := 0
	for fs.idx < n {
		c := fs.data[fs.idx]
		if c < '0' || c > '9' {
			break
		}
		val = val*10 + int(c-'0')
		fs.idx++
	}
	return val
}

func treeMoments(n, k int, g [][]int) []int64 {
	ncoeff := n
	if ncoeff > k {
		ncoeff = k
	}
	L := ncoeff / 2

	parent := make([]int, n)
	for i := 0; i < n; i++ {
		parent[i] = -2
	}
	order := make([]int, 0, n)
	stack := []int{0}
	parent[0] = -1
	for len(stack) > 0 {
		u := stack[len(stack)-1]
		stack = stack[:len(stack)-1]
		order = append(order, u)
		for _, v := range g[u] {
			if v == parent[u] {
				continue
			}
			parent[v] = u
			stack = append(stack, v)
		}
	}

	dp0 := make([][]int64, n)
	dp1 := make([][]int64, n)

	for idx := n - 1; idx >= 0; idx-- {
		u := order[idx]
		cur0 := make([]int64, L+1)
		cur1 := make([]int64, L+1)
		cur0[0] = 1

		for _, v := range g[u] {
			if parent[v] != u {
				continue
			}

			totV := make([]int64, L+1)
			for b := 0; b <= L; b++ {
				x := dp0[v][b] + dp1[v][b]
				if x >= MOD {
					x -= MOD
				}
				totV[b] = x
			}

			new0 := make([]int64, L+1)
			new1 := make([]int64, L+1)

			for a := 0; a <= L; a++ {
				ca0 := cur0[a]
				ca1 := cur1[a]
				if ca0 == 0 && ca1 == 0 {
					continue
				}
				maxB := L - a
				for b := 0; b <= maxB; b++ {
					tv := totV[b]
					if tv != 0 {
						if ca0 != 0 {
							new0[a+b] = (new0[a+b] + ca0*tv) % MOD
						}
						if ca1 != 0 {
							new1[a+b] = (new1[a+b] + ca1*tv) % MOD
						}
					}
					if ca0 != 0 && a+b+1 <= L {
						d0 := dp0[v][b]
						if d0 != 0 {
							new1[a+b+1] = (new1[a+b+1] + ca0*d0) % MOD
						}
					}
				}
			}

			cur0, cur1 = new0, new1
		}

		dp0[u] = cur0
		dp1[u] = cur1
	}

	c := make([]int64, ncoeff+1)
	c[0] = 1
	for j := 1; j <= L; j++ {
		pos := 2 * j
		if pos > ncoeff {
			break
		}
		val := dp0[0][j] + dp1[0][j]
		if val >= MOD {
			val -= MOD
		}
		if j%2 == 1 && val != 0 {
			val = MOD - val
		}
		c[pos] = val
	}

	p := make([]int64, k+1)
	p[0] = int64(n) % MOD

	for m := 1; m <= k; m++ {
		var s int64
		maxI := m - 1
		if maxI > ncoeff {
			maxI = ncoeff
		}
		for i := 1; i <= maxI; i++ {
			if c[i] == 0 || p[m-i] == 0 {
				continue
			}
			s = (s + c[i]*p[m-i]) % MOD
		}
		if m <= ncoeff && c[m] != 0 {
			s = (s + int64(m)*c[m]) % MOD
		}
		if s == 0 {
			p[m] = 0
		} else {
			p[m] = MOD - s
		}
	}

	return p
}

func main() {
	fs := NewFastScanner()
	n1 := fs.nextInt()
	n2 := fs.nextInt()
	k := fs.nextInt()

	g1 := make([][]int, n1)
	for i := 0; i < n1-1; i++ {
		u := fs.nextInt() - 1
		v := fs.nextInt() - 1
		g1[u] = append(g1[u], v)
		g1[v] = append(g1[v], u)
	}

	g2 := make([][]int, n2)
	for i := 0; i < n2-1; i++ {
		u := fs.nextInt() - 1
		v := fs.nextInt() - 1
		g2[u] = append(g2[u], v)
		g2[v] = append(g2[v], u)
	}

	p1 := treeMoments(n1, k, g1)
	p2 := treeMoments(n2, k, g2)

	comb := make([][]int64, k+1)
	for i := 0; i <= k; i++ {
		comb[i] = make([]int64, i+1)
		comb[i][0] = 1
		comb[i][i] = 1
		for j := 1; j < i; j++ {
			comb[i][j] = comb[i-1][j-1] + comb[i-1][j]
			if comb[i][j] >= MOD {
				comb[i][j] -= MOD
			}
		}
	}

	var ans int64
	for t := 0; t <= k; t++ {
		ans = (ans + comb[k][t]*p1[t]%MOD*p2[k-t]) % MOD
	}

	out := bufio.NewWriterSize(os.Stdout, 1<<20)
	fmt.Fprintln(out, ans)
	out.Flush()
}
```