← Home
```go
package main

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

const MOD = 1000000007
const MAXA = 200005

var spf [MAXA]int32
var inv [MAXA]int32

type Node struct {
	ls, rs int32
	val    int32
}

var tree []Node

type upd struct {
	pos int32
	val int32
}

func updateTreeBatch(node int32, l, r int32, upds []upd) int32 {
	newNode := int32(len(tree))
	tree = append(tree, tree[node])

	mul := int64(1)
	for i := 0; i < len(upds); i++ {
		mul = (mul * int64(upds[i].val)) % MOD
	}
	tree[newNode].val = int32((int64(tree[newNode].val) * mul) % MOD)

	if l == r {
		return newNode
	}

	mid := (l + r) >> 1
	split := 0
	for split < len(upds) && upds[split].pos <= mid {
		split++
	}

	if split > 0 {
		tree[newNode].ls = updateTreeBatch(tree[node].ls, l, mid, upds[:split])
	}
	if split < len(upds) {
		tree[newNode].rs = updateTreeBatch(tree[node].rs, mid+1, r, upds[split:])
	}

	return newNode
}

func queryTree(node int32, l, r int32, ql, qr int32) int32 {
	if node == 0 {
		return 1
	}
	if ql <= l && r <= qr {
		return tree[node].val
	}
	mid := (l + r) >> 1
	res := int32(1)
	if ql <= mid {
		res = int32((int64(res) * int64(queryTree(tree[node].ls, l, mid, ql, qr))) % MOD)
	}
	if qr > mid {
		res = int32((int64(res) * int64(queryTree(tree[node].rs, mid+1, r, ql, qr))) % MOD)
	}
	return res
}

func main() {
	for i := int32(2); i < MAXA; i++ {
		if spf[i] == 0 {
			for j := i; j < MAXA; j += i {
				if spf[j] == 0 {
					spf[j] = i
				}
			}
		}
	}

	inv[1] = 1
	for i := int32(2); i < MAXA; i++ {
		inv[i] = int32((int64(MOD) - int64(MOD/i)) * int64(inv[MOD%i]) % MOD)
	}

	scanner := bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	buf := make([]byte, 1024*1024)
	scanner.Buffer(buf, 1024*1024*10)

	scanInt := func() int32 {
		scanner.Scan()
		b := scanner.Bytes()
		res := int32(0)
		for _, v := range b {
			res = res*10 + int32(v-'0')
		}
		return res
	}

	if !scanner.Scan() {
		return
	}
	bBytes := scanner.Bytes()
	n := int32(0)
	for _, v := range bBytes {
		n = n*10 + int32(v-'0')
	}

	a := make([]int32, n+1)
	for i := int32(1); i <= n; i++ {
		a[i] = scanInt()
	}

	tree = make([]Node, 1, 5000000)
	tree[0] = Node{0, 0, 1}

	roots := make([]int32, n+1)
	roots[0] = 0

	prev := make([]int32, MAXA)

	for i := int32(1); i <= n; i++ {
		x := a[i]
		var upds []upd

		for x > 1 {
			p := spf[x]
			pk := int32(1)
			for x%p == 0 {
				x /= p
				pk *= p

				upds = append(upds, upd{pos: i, val: p})
				if prev[pk] != 0 {
					upds = append(upds, upd{pos: prev[pk], val: inv[p]})
				}
				prev[pk] = i
			}
		}

		combined := make([]upd, 0, len(upds))
		for j := 0; j < len(upds); j++ {
			u := upds[j]
			found := false
			for k := 0; k < len(combined); k++ {
				if combined[k].pos == u.pos {
					combined[k].val = int32((int64(combined[k].val) * int64(u.val)) % MOD)
					found = true
					break
				}
			}
			if !found {
				combined = append(combined, u)
			}
		}

		for j := 1; j < len(combined); j++ {
			k := j
			for k > 0 && combined[k-1].pos > combined[k].pos {
				combined[k-1], combined[k] = combined[k], combined[k-1]
				k--
			}
		}

		currRoot := roots[i-1]
		if len(combined) > 0 {
			currRoot = updateTreeBatch(currRoot, 1, n, combined)
		}
		roots[i] = currRoot
	}

	q := scanInt()
	last := int32(0)

	out := bufio.NewWriter(os.Stdout)
	for i := int32(0); i < q; i++ {
		x := scanInt()
		y := scanInt()

		l := int32((int64(last)+int64(x))%int64(n)) + 1
		r := int32((int64(last)+int64(y))%int64(n)) + 1
		if l > r {
			l, r = r, l
		}

		ans := queryTree(roots[r], 1, n, l, r)
		fmt.Fprintln(out, ans)
		last = ans
	}
	out.Flush()
}
```