```go
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func rotate(mat [][]byte) [][]byte {
n, m := len(mat), len(mat[0])
res := make([][]byte, m)
for i := 0; i < m; i++ {
res[i] = make([]byte, n)
for j := 0; j < n; j++ {
res[i][j] = mat[n-1-j][i]
}
}
return res
}
func serialize(mat [][]byte) string {
var b strings.Builder
n, m := len(mat), len(mat[0])
b.Grow(n*m + n - 1)
for i := 0; i < n; i++ {
if i > 0 {
b.WriteByte('|')
}
b.Write(mat[i])
}
return b.String()
}
func canonical(mat [][]byte) string {
best := serialize(mat)
cur := mat
for i := 0; i < 3; i++ {
cur = rotate(cur)
s := serialize(cur)
if s < best {
best = s
}
}
return best
}
func main() {
in := bufio.NewReader(os.Stdin)
var A, B int
if _, err := fmt.Fscan(in, &A, &B); err != nil {
return
}
pic := make([][]byte, A)
for i := 0; i < A; i++ {
var s string
fmt.Fscan(in, &s)
pic[i] = []byte(s)
}
count := 0
bestArea := 1 << 30
bestX, bestY := 0, 0
for x := 1; x <= A; x++ {
if A%x != 0 {
continue
}
for y := 1; y <= B; y++ {
if B%y != 0 {
continue
}
seen := make(map[string]struct{})
good := true
for r := 0; r < A && good; r += x {
for c := 0; c < B; c += y {
piece := make([][]byte, x)
for i := 0; i < x; i++ {
row := make([]byte, y)
copy(row, pic[r+i][c:c+y])
piece[i] = row
}
sig := canonical(piece)
if _, ok := seen[sig]; ok {
good = false
break
}
seen[sig] = struct{}{}
}
}
if good {
count++
area := x * y
if area < bestArea || (area == bestArea && x < bestX) {
bestArea = area
bestX, bestY = x, y
}
}
}
}
out := bufio.NewWriter(os.Stdout)
fmt.Fprintln(out, count)
fmt.Fprintln(out, bestX, bestY)
out.Flush()
}
```