package main
import (
"io"
"math/bits"
"os"
"strconv"
)
const MOD int64 = 998244353
type FastScanner struct {
data []byte
idx int
n int
}
func NewFastScanner() *FastScanner {
data, _ := io.ReadAll(os.Stdin)
return &FastScanner{data: data, n: len(data)}
}
func (fs *FastScanner) NextInt() int {
for fs.idx < fs.n && (fs.data[fs.idx] < '0' || fs.data[fs.idx] > '9') {
fs.idx++
}
val := 0
for fs.idx < fs.n {
b := fs.data[fs.idx]
if b < '0' || b > '9' {
break
}
val = val*10 + int(b-'0')
fs.idx++
}
return val
}
func main() {
fs := NewFastScanner()
n := fs.NextInt()
q := fs.NextInt()
a := make([]uint8, n+1)
for i := 1; i <= n; i++ {
a[i] = uint8(fs.NextInt())
}
stride := n + 1
valPref := make([]uint32, 51*stride)
var valBase [51]int
for v := 0; v <= 50; v++ {
base := v * stride
valBase[v] = base
var cur uint32
vv := uint8(v)
for i := 1; i <= n; i++ {
if a[i] == vv {
cur++
}
valPref[base+i] = cur
}
}
var parity [64][51]uint8
for s := 1; s < 64; s++ {
for v := 0; v <= 50; v++ {
if bits.OnesCount8(uint8(s&v))&1 == 1 {
parity[s][v] = 1
}
}
}
maskPref := make([]uint32, 64*stride)
var maskBase [64]int
for s := 1; s < 64; s++ {
base := s * stride
maskBase[s] = base
var cur uint32
for i := 1; i <= n; i++ {
cur += uint32(parity[s][a[i]])
maskPref[base+i] = cur
}
}
var comb [51][8]int64
comb[0][0] = 1
for i := 1; i <= 50; i++ {
comb[i][0] = 1
for k := 1; k <= 7; k++ {
comb[i][k] = comb[i-1][k]
comb[i][k] += comb[i-1][k-1]
}
}
var coeff [51][51][8]int32
for d := 0; d <= 50; d++ {
for c := 0; c <= d; c++ {
p := d - c
for k := 0; k <= 7; k++ {
var v int64
for t := 0; t <= k; t++ {
if t <= c && k-t <= p {
term := comb[c][t] * comb[p][k-t]
if t&1 == 1 {
v -= term
} else {
v += term
}
}
}
coeff[d][c][k] = int32(v)
}
}
}
out := make([]byte, 0, q*20)
for ; q > 0; q-- {
l := fs.NextInt()
r := fs.NextInt()
left := l - 1
length := r - l + 1
cnt0 := int(valPref[valBase[0]+r] - valPref[valBase[0]+left])
if cnt0 > 0 {
out = strconv.AppendInt(out, int64(length-1), 10)
out = append(out, ' ')
out = strconv.AppendInt(out, int64(cnt0)%MOD, 10)
out = append(out, '\n')
continue
}
var pairWays int64
dup := false
for v := 1; v <= 50; v++ {
c := int64(valPref[valBase[v]+r] - valPref[valBase[v]+left])
if c >= 2 {
dup = true
pairWays += c * (c - 1) / 2
}
}
if dup {
out = strconv.AppendInt(out, int64(length-2), 10)
out = append(out, ' ')
out = strconv.AppendInt(out, pairWays%MOD, 10)
out = append(out, '\n')
continue
}
if length < 3 {
out = append(out, '-', '1', '\n')
continue
}
d := length
var sum3, sum4, sum5, sum6, sum7 int64
sum3 = int64(coeff[d][0][3])
sum4 = int64(coeff[d][0][4])
sum5 = int64(coeff[d][0][5])
sum6 = int64(coeff[d][0][6])
sum7 = int64(coeff[d][0][7])
for s := 1; s < 64; s++ {
c := int(maskPref[maskBase[s]+r] - maskPref[maskBase[s]+left])
sum3 += int64(coeff[d][c][3])
sum4 += int64(coeff[d][c][4])
sum5 += int64(coeff[d][c][5])
sum6 += int64(coeff[d][c][6])
sum7 += int64(coeff[d][c][7])
}
c3 := sum3 / 64
if c3 > 0 {
out = strconv.AppendInt(out, int64(length-3), 10)
out = append(out, ' ')
out = strconv.AppendInt(out, c3%MOD, 10)
out = append(out, '\n')
continue
}
c4 := sum4 / 64
if c4 > 0 {
out = strconv.AppendInt(out, int64(length-4), 10)
out = append(out, ' ')
out = strconv.AppendInt(out, c4%MOD, 10)
out = append(out, '\n')
continue
}
c5 := sum5 / 64
if c5 > 0 {
out = strconv.AppendInt(out, int64(length-5), 10)
out = append(out, ' ')
out = strconv.AppendInt(out, c5%MOD, 10)
out = append(out, '\n')
continue
}
c6 := sum6 / 64
if c6 > 0 {
out = strconv.AppendInt(out, int64(length-6), 10)
out = append(out, ' ')
out = strconv.AppendInt(out, c6%MOD, 10)
out = append(out, '\n')
continue
}
c7 := sum7 / 64
if c7 > 0 {
out = strconv.AppendInt(out, int64(length-7), 10)
out = append(out, ' ')
out = strconv.AppendInt(out, c7%MOD, 10)
out = append(out, '\n')
continue
}
out = append(out, '-', '1', '\n')
}
os.Stdout.Write(out)
}