← Home
For problem statement at 1000-1999/1500-1599/1580-1589/1582/problemG.txt this is a correct solution, but verifier at 1000-1999/1500-1599/1580-1589/1582/verifierG.go ends with All tests passed can you fix the verifier? package main

import (
	"bufio"
	"io"
	"os"
	"strconv"
)

type FastScanner struct {
	data []byte
	idx  int
}

func (fs *FastScanner) skip() {
	for fs.idx < len(fs.data) && fs.data[fs.idx] <= ' ' {
		fs.idx++
	}
}

func (fs *FastScanner) nextInt() int {
	fs.skip()
	v := 0
	for fs.idx < len(fs.data) {
		c := fs.data[fs.idx]
		if c < '0' || c > '9' {
			break
		}
		v = v*10 + int(c-'0')
		fs.idx++
	}
	return v
}

func (fs *FastScanner) nextToken() []byte {
	fs.skip()
	start := fs.idx
	for fs.idx < len(fs.data) && fs.data[fs.idx] > ' ' {
		fs.idx++
	}
	return fs.data[start:fs.idx]
}

func main() {
	data, _ := io.ReadAll(os.Stdin)
	fs := FastScanner{data: data}

	n := fs.nextInt()
	a := make([]int32, n)
	maxV := 1
	for i := 0; i < n; i++ {
		v := fs.nextInt()
		a[i] = int32(v)
		if v > maxV {
			maxV = v
		}
	}
	tok := fs.nextToken()
	b := make([]byte, len(tok))
	copy(b, tok)
	data = nil
	fs.data = nil

	if maxV < 2 {
		ans := int64(n) * int64(n+1) / 2
		out := bufio.NewWriterSize(os.Stdout, 1<<20)
		out.WriteString(strconv.FormatInt(ans, 10))
		out.Flush()
		return
	}

	spf := make([]int32, maxV+1)
	primes := make([]int, 0, 80000)
	for i := 2; i <= maxV; i++ {
		if spf[i] == 0 {
			spf[i] = int32(i)
			primes = append(primes, i)
		}
		si := int(spf[i])
		for _, p := range primes {
			v := p * i
			if v > maxV || p > si {
				break
			}
			spf[v] = int32(p)
		}
	}

	primeID := make([]int32, maxV+1)
	counts := make([]int32, 0, 80000)

	for i := 0; i < n; i++ {
		x := int(a[i])
		for x > 1 {
			p := int(spf[x])
			for x > 1 && int(spf[x]) == p {
				x /= p
			}
			id1 := primeID[p]
			if id1 == 0 {
				counts = append(counts, 0)
				id1 = int32(len(counts))
				primeID[p] = id1
			}
			counts[id1-1]++
		}
	}

	P := len(counts)
	if P == 0 {
		ans := int64(n) * int64(n+1) / 2
		out := bufio.NewWriterSize(os.Stdout, 1<<20)
		out.WriteString(strconv.FormatInt(ans, 10))
		out.Flush()
		return
	}

	occOffset := make([]int32, P+1)
	maxCount := 0
	for i := 0; i < P; i++ {
		occOffset[i+1] = occOffset[i] + counts[i]
		if int(counts[i]) > maxCount {
			maxCount = int(counts[i])
		}
	}
	M := int(occOffset[P])

	positions := make([]int32, M)
	weights := make([]int8, M)
	cursor := make([]int32, P)
	copy(cursor, occOffset[:P])

	for i := 0; i < n; i++ {
		x := int(a[i])
		if x == 1 {
			continue
		}
		s := int8(1)
		if b[i] == '/' {
			s = -1
		}
		for x > 1 {
			p := int(spf[x])
			e := 0
			for x > 1 && int(spf[x]) == p {
				x /= p
				e++
			}
			id := int(primeID[p] - 1)
			idx := cursor[id]
			positions[idx] = int32(i + 1)
			weights[idx] = int8(e) * s
			cursor[id] = idx + 1
		}
	}

	b = nil

	badOffset := make([]int32, P+1)
	for i := 0; i < P; i++ {
		badOffset[i+1] = badOffset[i] + counts[i] + 1
	}
	badPos := make([]int32, int(badOffset[P]))

	tempCum := make([]int32, maxCount+1)
	tempStack := make([]int, maxCount+1)

	for id := 0; id < P; id++ {
		start := int(occOffset[id])
		m := int(counts[id])
		bstart := int(badOffset[id])

		cum := tempCum[:m+1]
		cum[0] = 0
		for j := 1; j <= m; j++ {
			cum[j] = cum[j-1] + int32(weights[start+j-1])
		}

		top := 0
		for i := m; i >= 0; i-- {
			ci := cum[i]
			for top > 0 && cum[tempStack[top-1]] >= ci {
				top--
			}
			if top == 0 {
				badPos[bstart+i] = int32(n + 1)
			} else {
				badPos[bstart+i] = positions[start+tempStack[top-1]-1]
			}
			tempStack[top] = i
			top++
		}
	}

	size := 1
	for size < P {
		size <<= 1
	}
	inf := int32(n + 1)
	seg := make([]int32, size<<1)
	for i := range seg {
		seg[i] = inf
	}
	for i := 0; i < P; i++ {
		seg[size+i] = badPos[int(badOffset[i])]
	}
	for i := size - 1; i >= 1; i-- {
		left := seg[i<<1]
		right := seg[i<<1|1]
		if left < right {
			seg[i] = left
		} else {
			seg[i] = right
		}
	}

	currentIdx := cursor
	for i := 0; i < P; i++ {
		currentIdx[i] = 0
	}

	var ans int64

	for l := 1; l <= n; l++ {
		ans += int64(seg[1] - int32(l))

		x := int(a[l-1])
		for x > 1 {
			p := int(spf[x])
			for x > 1 && int(spf[x]) == p {
				x /= p
			}
			id := int(primeID[p] - 1)
			currentIdx[id]++
			val := badPos[int(badOffset[id]+currentIdx[id])]
			leaf := size + id
			if seg[leaf] != val {
				seg[leaf] = val
				for pos := leaf >> 1; pos > 0; pos >>= 1 {
					nv := seg[pos<<1]
					if seg[pos<<1|1] < nv {
						nv = seg[pos<<1|1]
					}
					if seg[pos] == nv {
						break
					}
					seg[pos] = nv
				}
			}
		}
	}

	out := bufio.NewWriterSize(os.Stdout, 1<<20)
	out.WriteString(strconv.FormatInt(ans, 10))
	out.Flush()
}