```go
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
const MOD = 998244353
const MAX_VAL = 1000000
var fact []int64
func power(a, b int64) int64 {
res := int64(1)
for b > 0 {
if b&1 == 1 {
res = (res * a) % MOD
}
a = (a * a) % MOD
b >>= 1
}
return res
}
func inverse(n int64) int64 {
return power(n, MOD-2)
}
func initFact(n int) {
fact = make([]int64, n+1)
fact[0] = 1
for i := 1; i <= n; i++ {
fact[i] = (fact[i-1] * int64(i)) % MOD
}
}
func main() {
scanner := bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanWords)
if !scanner.Scan() {
return
}
n, _ := strconv.Atoi(scanner.Text())
counts := make(map[int]int)
for i := 0; i < 2*n; i++ {
scanner.Scan()
val, _ := strconv.Atoi(scanner.Text())
counts[val]++
}
isPrime := make([]bool, MAX_VAL+1)
for i := 2; i <= MAX_VAL; i++ {
isPrime[i] = true
}
for i := 2; i*i <= MAX_VAL; i++ {
if isPrime[i] {
for j := i * i; j <= MAX_VAL; j += i {
isPrime[j] = false
}
}
}
initFact(2 * n)
denom := int64(1)
for _, cnt := range counts {
denom = (denom * fact[cnt]) % MOD
}
baseFactor := (fact[n] * inverse(denom)) % MOD
dp := make([]int64, n+1)
dp[0] = 1
for val, cnt := range counts {
if isPrime[val] {
c := int64(cnt)
for j := n; j >= 1; j-- {
dp[j] = (dp[j] + dp[j-1]*c) % MOD
}
}
}
fmt.Println((baseFactor * dp[n]) % MOD)
}
```