```go
package main
import (
"bufio"
"fmt"
"math"
"os"
"strconv"
)
type MaxCount struct {
maxVal int
count int64
}
func combine(a, b MaxCount) MaxCount {
if a.maxVal > b.maxVal {
return a
}
if b.maxVal > a.maxVal {
return b
}
return MaxCount{a.maxVal, a.count + b.count}
}
func main() {
scanner := bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanWords)
buf := make([]byte, 1024*1024)
scanner.Buffer(buf, 10*1024*1024)
scanInt := func() int {
scanner.Scan()
res, _ := strconv.Atoi(scanner.Text())
return res
}
if !scanner.Scan() {
return
}
n, _ := strconv.Atoi(scanner.Text())
m := scanInt()
r := scanInt()
if n-2*r <= 0 || m-2*r <= 0 {
fmt.Println("0 0")
return
}
grid := make([][]int, n+1)
grid_pref := make([][]int, n+1)
for i := 1; i <= n; i++ {
grid[i] = make([]int, m+1)
grid_pref[i] = make([]int, m+1)
for j := 1; j <= m; j++ {
grid[i][j] = scanInt()
grid_pref[i][j] = grid_pref[i][j-1] + grid[i][j]
}
}
w := make([]int, r+1)
for y := 0; y <= r; y++ {
rem := r*r - y*y
val := int(math.Sqrt(float64(rem)))
for (val+1)*(val+1) <= rem {
val++
}
for val*val > rem {
val--
}
w[y] = val
}
W := make([]int, 2*r+1)
for Y := 0; Y <= 2*r; Y++ {
W[Y] = -1
}
for y1 := -r; y1 <= r; y1++ {
for y2 := -r; y2 <= r; y2++ {
Y := y1 + y2
if Y < 0 {
Y = -Y
}
if Y <= 2*r {
abs_y1 := y1
if abs_y1 < 0 {
abs_y1 = -abs_y1
}
w1 := w[abs_y1]
abs_y2 := y2
if abs_y2 < 0 {
abs_y2 = -abs_y2
}
w2 := w[abs_y2]
if w1+w2 > W[Y] {
W[Y] = w1 + w2
}
}
}
}
NPrime := n - 2*r
MPrime := m - 2*r
S := make([][]int, NPrime+1)
for i := 1; i <= NPrime; i++ {
S[i] = make([]int, MPrime+1)
y := i + r
for j := 1; j <= MPrime; j++ {
x := j + r
sum := 0
for dy := -r; dy <= r; dy++ {
abs_dy := dy
if abs_dy < 0 {
abs_dy = -abs_dy
}
w_val := w[abs_dy]
sum += grid_pref[y+dy][x+w_val] - grid_pref[y+dy][x-w_val-1]
}
S[i][j] = sum
}
}
pref := make([][]MaxCount, NPrime+1)
suff := make([][]MaxCount, NPrime+1)
for i := 1; i <= NPrime; i++ {
pref[i] = make([]MaxCount, MPrime+2)
suff[i] = make([]MaxCount, MPrime+2)
pref[i][0] = MaxCount{-1, 0}
cur := MaxCount{-1, 0}
for j := 1; j <= MPrime; j++ {
cur = combine(cur, MaxCount{S[i][j], 1})
pref[i][j] = cur
}
pref[i][MPrime+1] = cur
suff[i][MPrime+1] = MaxCount{-1, 0}
cur = MaxCount{-1, 0}
for j := MPrime; j >= 1; j-- {
cur = combine(cur, MaxCount{S[i][j], 1})
suff[i][j] = cur
}
suff[i][0] = cur
}
row_max := make([]MaxCount, NPrime+1)
for i := 1; i <= NPrime; i++ {
row_max[i] = pref[i][MPrime]
}
pref_row := make([]MaxCount, NPrime+2)
suff_row := make([]MaxCount, NPrime+2)
for i := 0; i <= NPrime+1; i++ {
pref_row[i] = MaxCount{-1, 0}
suff_row[i] = MaxCount{-1, 0}
}
cur := MaxCount{-1, 0}
for i := 1; i <= NPrime; i++ {
cur = combine(cur, row_max[i])
pref_row[i] = cur
}
cur = MaxCount{-1, 0}
for i := NPrime; i >= 1; i-- {
cur = combine(cur, row_max[i])
suff_row[i] = cur
}
best_sum := -1
best_count := int64(0)
for i1 := 1; i1 <= NPrime; i1++ {
for j1 := 1; j1 <= MPrime; j1++ {
res := MaxCount{-1, 0}
idx := i1 - 2*r - 1
if idx >= 1 {
if idx > NPrime {
idx = NPrime
}
res = combine(res, pref_row[idx])
}
idx = i1 + 2*r + 1
if idx <= NPrime {
if idx < 1 {
idx = 1
}
res = combine(res, suff_row[idx])
}
start := i1 - 2*r
if start < 1 {
start = 1
}
end := i1 + 2*r
if end > NPrime {
end = NPrime
}
for i2 := start; i2 <= end; i2++ {
Y := i1 - i2
if Y < 0 {
Y = -Y
}
left_end := j1 - W[Y] - 1
if left_end < 0 {
left_end = 0
}
if left_end > MPrime {
left_end = MPrime
}
res = combine(res, pref[i2][left_end])
right_start := j1 + W[Y] + 1
if right_start < 1 {
right_start = 1
}
if right_start > MPrime+1 {
right_start = MPrime + 1
}
res = combine(res, suff[i2][right_start])
}
if res.maxVal != -1 {
current_sum := S[i1][j1] + res.maxVal
if current_sum > best_sum {
best_sum = current_sum
best_count = res.count
} else if current_sum == best_sum {
best_count += res.count
}
}
}
}
if best_sum == -1 {
fmt.Println("0 0")
} else {
fmt.Println(best_sum, best_count/2)
}
}
```