← Home
For problem statement at 2000-2999/2000-2099/2040-2049/2040/problemF.txt this is a correct solution, but verifier at 2000-2999/2000-2099/2040-2049/2040/verifierF.go ends with All tests passed. can you fix the verifier? ```go
package main

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

const MOD uint32 = 998244353

type Test struct {
	a, b, c int
	k       int
	d       []int
}

type FastScanner struct {
	r *bufio.Reader
}

func NewFastScanner() *FastScanner {
	return &FastScanner{r: bufio.NewReaderSize(os.Stdin, 1<<20)}
}

func (fs *FastScanner) NextInt() int {
	sign := 1
	val := 0
	c, err := fs.r.ReadByte()
	for (c < '0' || c > '9') && c != '-' {
		c, err = fs.r.ReadByte()
		if err != nil {
			return 0
		}
	}
	if c == '-' {
		sign = -1
		c, _ = fs.r.ReadByte()
	}
	for c >= '0' && c <= '9' {
		val = val*10 + int(c-'0')
		c, err = fs.r.ReadByte()
		if err != nil {
			break
		}
	}
	return val * sign
}

func mulMod(a, b uint32) uint32 {
	return uint32((uint64(a) * uint64(b)) % uint64(MOD))
}

func addMod(a, b uint32) uint32 {
	x := a + b
	if x >= MOD {
		x -= MOD
	}
	return x
}

func powMod(a uint32, e int64) uint32 {
	res := uint32(1)
	base := a
	for e > 0 {
		if (e & 1) != 0 {
			res = mulMod(res, base)
		}
		base = mulMod(base, base)
		e >>= 1
	}
	return res
}

func gcd(a, b int64) int64 {
	for b != 0 {
		a, b = b, a%b
	}
	if a < 0 {
		return -a
	}
	return a
}

func lcm(a, b int64) int64 {
	return a / gcd(a, b) * b
}

func sieveLinearMuLP(N int) ([]int32, []int8) {
	lp := make([]int32, N+1)
	mu := make([]int8, N+1)
	mu[1] = 1
	primes := make([]int32, 0, N/10)
	for i := 2; i <= N; i++ {
		if lp[i] == 0 {
			lp[i] = int32(i)
			primes = append(primes, int32(i))
			mu[i] = -1
		}
		for _, p := range primes {
			v := int(p) * i
			if v > N {
				break
			}
			lp[v] = p
			if i%int(p) == 0 {
				mu[v] = 0
				break
			} else {
				mu[v] = -mu[i]
			}
		}
	}
	return lp, mu
}

func precomputeFact(N int) ([]uint32, []uint32) {
	fact := make([]uint32, N+1)
	invfact := make([]uint32, N+1)
	fact[0] = 1
	for i := 1; i <= N; i++ {
		fact[i] = mulMod(fact[i-1], uint32(i))
	}
	invfact[N] = powMod(fact[N], int64(MOD-2))
	for i := N - 1; i >= 0; i-- {
		invfact[i] = mulMod(invfact[i+1], uint32(i+1))
	}
	return fact, invfact
}

func factorizeWithLP(n int, lp []int32, primes *[16]int, exps *[16]int) int {
	if n <= 1 {
		return 0
	}
	cnt := 0
	for n > 1 {
		p := int(lp[n])
		e := 0
		for n%p == 0 {
			n /= p
			e++
		}
		primes[cnt] = p
		exps[cnt] = e
		cnt++
	}
	return cnt
}

func genDivisorsFromFactors(primes *[16]int, exps *[16]int, cnt int) []int {
	res := make([]int, 1, 64)
	res[0] = 1
	for i := 0; i < cnt; i++ {
		p := primes[i]
		e := exps[i]
		size := len(res)
		mul := 1
		for j := 1; j <= e; j++ {
			mul *= p
			for k := 0; k < size; k++ {
				res = append(res, res[k]*mul)
			}
		}
	}
	return res
}

var gPos []int32
var gDenom []uint32
var gInvfact []uint32
var gCurrentD int

func dfsEnumMul(primes *[16]int, exps *[16]int, cnt int, idx int, curr int) {
	if idx == cnt {
		p := gPos[curr]
		if p > 0 {
			ii := int(p - 1)
			val := gInvfact[gCurrentD/curr]
			gDenom[ii] = mulMod(gDenom[ii], val)
		}
		return
	}
	p := primes[idx]
	exp := exps[idx]
	mul := 1
	for i := 0; i <= exp; i++ {
		dfsEnumMul(primes, exps, cnt, idx+1, curr*mul)
		mul *= p
	}
}

func main() {
	in := NewFastScanner()
	t := in.NextInt()
	tests := make([]Test, t)
	maxN := 0
	for i := 0; i < t; i++ {
		a := in.NextInt()
		b := in.NextInt()
		c := in.NextInt()
		k := in.NextInt()
		d := make([]int, k)
		for j := 0; j < k; j++ {
			d[j] = in.NextInt()
		}
		tests[i] = Test{a: a, b: b, c: c, k: k, d: d}
		n := a * b * c
		if n > maxN {
			maxN = n
		}
	}
	lp, mu := sieveLinearMuLP(maxN)
	fact, invfact := precomputeFact(maxN)

	// pos array for divisors mapping
	pos := make([]int32, maxN+1)

	out := bufio.NewWriterSize(os.Stdout, 1<<20)
	for _, tt := range tests {
		a := tt.a
		b := tt.b
		c := tt.c
		n := a * b * c

		// lcm(a,b,c)
		l := lcm(int64(a), int64(b))
		l = lcm(l, int64(c))

		// GCD of all d_i
		G := int64(tt.d[0])
		for i := 1; i < tt.k; i++ {
			G = gcd(G, int64(tt.d[i]))
		}
		g := int(gcd(G, l))

		// divisors of g
		var fpr, fex [16]int
		cntg := factorizeWithLP(g, lp, &fpr, &fex)
		divsG := genDivisorsFromFactors(&fpr, &fex, cntg)
		// map divisors to index
		for i := 0; i < len(divsG); i++ {
			pos[divsG[i]] = int32(i + 1)
		}
		denom := make([]uint32, len(divsG))
		for i := range denom {
			denom[i] = 1
		}

		// set globals for dfs
		gPos = pos
		gDenom = denom
		gInvfact = invfact

		// accumulate denominators
		for _, dval := range tt.d {
			gCurrentD = dval
			var p, e [16]int
			cnt := factorizeWithLP(dval, lp, &p, &e)
			dfsEnumMul(&p, &e, cnt, 0, 1)
		}

		// Burnside sum over L | g
		var S uint32 = 0

		// Precompute gcd(a, d), gcd(b, d), gcd(c, d) on the fly per L's divisor
		for idx, L := range divsG {
			norbits := n / L
			F := mulMod(fact[norbits], denom[idx])

			// compute W(L) = sum_{d|L} mu(L/d) * gcd(a,d)*gcd(b,d)*gcd(c,d)
			var prL, exL [16]int
			cntL := factorizeWithLP(L, lp, &prL, &exL)
			divsL := genDivisorsFromFactors(&prL, &exL, cntL)
			var W int64 = 0
			for _, d := range divsL {
				tq := L / d
				m := int64(mu[tq])
				if m == 0 {
					continue
				}
				ga := int(gcd(int64(a), int64(d)))
				gb := int(gcd(int64(b), int64(d)))
				gc := int(gcd(int64(c), int64(d)))
				W += m * int64(ga*gb*gc)
			}
			// W should be non-negative, but mod anyway
			wmod := uint32(((W%int64(MOD))+int64(MOD))%int64(MOD))
			term := mulMod(wmod, F)
			S = addMod(S, term)
		}

		invN := powMod(uint32(n), int64(MOD-2))
		ans := mulMod(S, invN)
		fmt.Fprintln(out, ans)

		// clear pos
		for _, L := range divsG {
			pos[L] = 0
		}
	}
	out.Flush()
}
```