```go
package main
import (
"fmt"
"io"
"os"
)
const MOD = 998244353
const G = 3
func power(base, exp int) int {
res := 1
base %= MOD
for exp > 0 {
if exp%2 == 1 {
res = res * base % MOD
}
base = base * base % MOD
exp /= 2
}
return res
}
var rt, irt [][]int
func initNTT(maxLen int) {
k := 0
for (1 << k) <= maxLen {
k++
}
rt = make([][]int, k)
irt = make([][]int, k)
for i := 1; i < k; i++ {
l := 1 << i
wlen := power(G, (MOD-1)/l)
iwlen := power(wlen, MOD-2)
rt[i] = make([]int, l/2)
irt[i] = make([]int, l/2)
w := 1
iw := 1
for j := 0; j < l/2; j++ {
rt[i][j] = w
irt[i][j] = iw
w = w * wlen % MOD
iw = iw * iwlen % MOD
}
}
}
func ntt(a []int, invert bool) {
n := len(a)
for i, j := 1, 0; i < n; i++ {
bit := n >> 1
for j&bit != 0 {
j ^= bit
bit >>= 1
}
j ^= bit
if i < j {
a[i], a[j] = a[j], a[i]
}
}
k := 1
for l := 2; l <= n; l <<= 1 {
var w []int
if invert {
w = irt[k]
} else {
w = rt[k]
}
half := l / 2
for i := 0; i < n; i += l {
for j := 0; j < half; j++ {
u := a[i+j]
v := a[i+j+half] * w[j] % MOD
a[i+j] = u + v
if a[i+j] >= MOD {
a[i+j] -= MOD
}
a[i+j+half] = u - v + MOD
if a[i+j+half] >= MOD {
a[i+j+half] -= MOD
}
}
}
k++
}
if invert {
invN := power(n, MOD-2)
for i := 0; i < n; i++ {
a[i] = a[i] * invN % MOD
}
}
}
func multiply(a, b []int) []int {
if len(a) == 0 || len(b) == 0 {
return []int{}
}
if len(a)*len(b) <= 256 {
res := make([]int, len(a)+len(b)-1)
for i, va := range a {
if va == 0 {
continue
}
for j, vb := range b {
res[i+j] = (res[i+j] + va*vb) % MOD
}
}
return res
}
n := 1
for n < len(a)+len(b)-1 {
n <<= 1
}
fa := make([]int, n)
fb := make([]int, n)
copy(fa, a)
copy(fb, b)
ntt(fa, false)
ntt(fb, false)
for i := 0; i < n; i++ {
fa[i] = fa[i] * fb[i] % MOD
}
ntt(fa, true)
return fa[:len(a)+len(b)-1]
}
func main() {
bBytes, err := io.ReadAll(os.Stdin)
if err != nil {
return
}
ptr := 0
readInt := func() int {
for ptr < len(bBytes) && (bBytes[ptr] < '0' || bBytes[ptr] > '9') {
ptr++
}
if ptr >= len(bBytes) {
return 0
}
res := 0
for ptr < len(bBytes) && bBytes[ptr] >= '0' && bBytes[ptr] <= '9' {
res = res*10 + int(bBytes[ptr]-'0')
ptr++
}
return res
}
n := readInt()
if n == 0 {
return
}
adj := make([][]int, n+1)
for i := 0; i < n-1; i++ {
u := readInt()
v := readInt()
adj[u] = append(adj[u], v)
adj[v] = append(adj[v], u)
}
q := make([]int, 0, n)
q = append(q, 1)
visited := make([]bool, n+1)
visited[1] = true
d := make([]int, n+1)
for i := 0; i < len(q); i++ {
u := q[i]
for _, v := range adj[u] {
if !visited[v] {
visited[v] = true
d[u]++
q = append(q, v)
}
}
}
freq := make(map[int]int)
for i := 1; i <= n; i++ {
if d[i] > 0 {
freq[d[i]]++
}
}
fact := make([]int, n+1)
invFact := make([]int, n+1)
fact[0] = 1
invFact[0] = 1
for i := 1; i <= n; i++ {
fact[i] = fact[i-1] * i % MOD
}
invFact[n] = power(fact[n], MOD-2)
for i := n - 1; i >= 1; i-- {
invFact[i] = invFact[i+1] * (i + 1) % MOD
}
getPoly := func(D, C int) []int {
poly := make([]int, C+1)
poly[0] = 1
D_pow := 1
for j := 1; j <= C; j++ {
D_pow = D_pow * D % MOD
comb := fact[C] * invFact[j] % MOD * invFact[C-j] % MOD
poly[j] = comb * D_pow % MOD
}
return poly
}
var polys [][]int
for D, C := range freq {
polys = append(polys, getPoly(D, C))
}
if len(polys) == 0 {
polys = append(polys, []int{1})
}
initNTT(1 << 20)
for len(polys) > 1 {
min1, min2 := -1, -1
for i := 0; i < len(polys); i++ {
if min1 == -1 || len(polys[i]) < len(polys[min1]) {
min2 = min1
min1 = i
} else if min2 == -1 || len(polys[i]) < len(polys[min2]) {
min2 = i
}
}
a := polys[min1]
b := polys[min2]
nextPolys := make([][]int, 0, len(polys)-1)
for i := 0; i < len(polys); i++ {
if i != min1 && i != min2 {
nextPolys = append(nextPolys, polys[i])
}
}
nextPolys = append(nextPolys, multiply(a, b))
polys = nextPolys
}
finalPoly := polys[0]
ans := 0
for k := 0; k < len(finalPoly); k++ {
if n-k < 0 {
break
}
term := finalPoly[k] * fact[n-k] % MOD
if k%2 == 1 {
ans = (ans - term + MOD) % MOD
} else {
ans = (ans + term) % MOD
}
}
fmt.Println(ans)
}
```