```go
package main
import (
"bufio"
"fmt"
"os"
)
const MOD = 998244353
func power(base, exp int64) int64 {
res := int64(1)
base = (base % MOD + MOD) % MOD
for exp > 0 {
if exp%2 == 1 {
res = (res * base) % MOD
}
base = (base * base) % MOD
exp /= 2
}
return res
}
func modInverse(n int64) int64 {
return power(n, MOD-2)
}
func add_poly(A, B []int64) []int64 {
n := len(A)
if len(B) > n {
n = len(B)
}
res := make([]int64, n)
for i := 0; i < n; i++ {
a, b := int64(0), int64(0)
if i < len(A) {
a = A[i]
}
if i < len(B) {
b = B[i]
}
res[i] = (a + b) % MOD
}
for len(res) > 1 && res[len(res)-1] == 0 {
res = res[:len(res)-1]
}
return res
}
func mul_poly(A, B []int64) []int64 {
if len(A) == 0 || len(B) == 0 {
return []int64{0}
}
res := make([]int64, len(A)+len(B)-1)
for i, a := range A {
if a == 0 {
continue
}
for j, b := range B {
res[i+j] = (res[i+j] + a*b) % MOD
}
}
return res
}
func eval_poly(P []int64, x int64) int64 {
x = (x%MOD + MOD) % MOD
res := int64(0)
pow := int64(1)
for _, c := range P {
res = (res + c*pow) % MOD
pow = (pow * x) % MOD
}
return res
}
func shift_poly_minus_1(P []int64) []int64 {
res := make([]int64, len(P))
for i, c := range P {
if c == 0 {
continue
}
term := []int64{1}
bin := []int64{MOD - 1, 1}
for k := 1; k <= i; k++ {
term = mul_poly(term, bin)
}
for j, val := range term {
res[j] = (res[j] + c*val) % MOD
}
}
for len(res) > 1 && res[len(res)-1] == 0 {
res = res[:len(res)-1]
}
return res
}
func interpolate(Y []int64) []int64 {
N := len(Y) - 1
Poly := []int64{0}
for i := 0; i <= N; i++ {
Term := []int64{Y[i]}
for j := 0; j <= N; j++ {
if i != j {
diff := int64(i - j)
inv := modInverse(diff)
c0 := (-int64(j) * inv) % MOD
if c0 < 0 {
c0 += MOD
}
c1 := inv
Term = mul_poly(Term, []int64{c0, c1})
}
}
Poly = add_poly(Poly, Term)
}
return Poly
}
func sum_poly(P []int64) []int64 {
D := len(P) - 1
if D < 0 {
return []int64{0}
}
pts := make([]int64, D+2)
for x := 0; x <= D+1; x++ {
pts[x] = eval_poly(P, int64(x))
}
S_pts := make([]int64, D+2)
S_pts[0] = pts[0]
for i := 1; i <= D+1; i++ {
S_pts[i] = (S_pts[i-1] + pts[i]) % MOD
}
return interpolate(S_pts)
}
type Interval struct {
L, R int64
P []int64
}
var intervals []Interval
func split_at(X int64) {
for i := 0; i < len(intervals); i++ {
iv := intervals[i]
if iv.L < X && X <= iv.R {
left := Interval{iv.L, X - 1, append([]int64(nil), iv.P...)}
right := Interval{X, iv.R, append([]int64(nil), iv.P...)}
intervals = append(intervals[:i], append([]Interval{left, right}, intervals[i+1:]...)...)
break
}
}
}
func min(a, b int64) int64 {
if a < b {
return a
}
return b
}
func max(a, b int64) int64 {
if a > b {
return a
}
return b
}
func main() {
reader := bufio.NewReader(os.Stdin)
var n int
fmt.Fscan(reader, &n)
var x int64
fmt.Fscan(reader, &x)
d := make([]int64, n)
for i := 0; i < n; i++ {
fmt.Fscan(reader, &d[i])
}
V := make([]int64, n+1)
V[0] = x
for i := 1; i <= n; i++ {
V[i] = V[i-1] + d[i-1]
}
min_reach := make([]int64, n+1)
max_reach := make([]int64, n+1)
min_reach[0] = V[0]
max_reach[0] = V[0]
for i := 1; i <= n; i++ {
min_reach[i] = min(min_reach[i-1], V[i])
max_reach[i] = max(max_reach[i-1], V[i])
}
max_suff := make([]int64, n+1)
max_suff[n] = V[n]
for i := n - 1; i >= 0; i-- {
max_suff[i] = max(max_suff[i+1], V[i])
}
M := int64(0)
for i := 0; i <= n; i++ {
diff := max_suff[i] - min_reach[i]
if diff > M {
M = diff
}
}
type VRange struct {
L, R int64
}
var v_ranges []VRange
if V[0] <= max_reach[n]-M {
v_ranges = append(v_ranges, VRange{V[0], max_reach[n] - M})
}
for k := 1; k <= n; k++ {
if V[k] < min_reach[k-1] {
L := V[k]
R := min(min_reach[k-1]-1, max_suff[k]-M)
if L <= R {
v_ranges = append(v_ranges, VRange{L, R})
}
}
}
INF := int64(4000000000)
intervals = []Interval{{-INF, INF, []int64{0}}}
for _, vr := range v_ranges {
split_at(vr.L)
split_at(vr.R + 1)
for i := 0; i < len(intervals); i++ {
if intervals[i].L >= vr.L && intervals[i].R <= vr.R {
intervals[i].P = []int64{1}
}
}
}
apply_inc := func(A, B int64) {
split_at(A)
split_at(B + 1)
accum := int64(0)
for i := 0; i < len(intervals); i++ {
iv := intervals[i]
if iv.L >= A && iv.R <= B {
S := sum_poly(iv.P)
S_L_minus_1 := eval_poly(S, iv.L-1)
S_R := eval_poly(S, iv.R)
const_term := (accum - S_L_minus_1) % MOD
if const_term < 0 {
const_term += MOD
}
intervals[i].P = add_poly(S, []int64{const_term})
accum = (accum + S_R - S_L_minus_1) % MOD
if accum < 0 {
accum += MOD
}
}
}
}
apply_dec := func(A, B int64) {
type Shift struct {
L, R int64
P []int64
}
var shifts []Shift
for _, iv := range intervals {
L_new := max(iv.L+1, A+1)
R_new := min(iv.R+1, B+1)
if L_new <= R_new {
shifted_P := shift_poly_minus_1(iv.P)
shifts = append(shifts, Shift{L_new, R_new, shifted_P})
}
}
for _, sh := range shifts {
split_at(sh.L)
split_at(sh.R + 1)
for i := 0; i < len(intervals); i++ {
if intervals[i].L >= sh.L && intervals[i].R <= sh.R {
intervals[i].P = add_poly(intervals[i].P, sh.P)
}
}
}
}
apply_inc(V[0], V[0])
for s := 1; s <= n; s++ {
if d[s-1] > 0 {
apply_inc(V[s-1]+1, V[s])
} else {
apply_dec(V[s], V[s-1]-1)
}
}
ans := int64(0)
for _, vr := range v_ranges {
L_target := vr.L + M + 1
R_target := vr.R + M + 1
split_at(L_target)
split_at(R_target + 1)
for i := 0; i < len(intervals); i++ {
if intervals[i].L >= L_target && intervals[i].R <= R_target {
S := sum_poly(intervals[i].P)
val := (eval_poly(S, intervals[i].R) - eval_poly(S, intervals[i].L-1)) % MOD
if val < 0 {
val += MOD
}
ans = (ans + val) % MOD
}
}
}
fmt.Printf("%d %d\n", M+1, ans)
}
```