Problem:
Score : 500 points

Problem Statement

Snuke has two boards, each divided into a grid with N rows and N columns.
For both of these boards, the square at the i-th row from the top and the j-th column from the left is called Square (i,j).

There is a lowercase English letter written in each square on the first board. The letter written in Square (i,j) is S_{i,j}. On the second board, nothing is written yet.

Snuke will write letters on the second board, as follows:

First, choose two integers A and B ( 0 \leq A, B < N ).

Write one letter in each square on the second board.
Specifically, write the letter written in Square ( i+A, j+B ) on the first board into Square (i,j) on the second board.
Here, the k-th row is also represented as the (N+k)-th row, and the k-th column is also represented as the (N+k)-th column.

After this operation, the second board is called a good board when, for every i and j ( 1 \leq i, j \leq N ), the letter in Square (i,j) and the letter in Square (j,i) are equal.

Find the number of the ways to choose integers A and B ( 0 \leq A, B < N ) such that the second board is a good board.

Constraints

1 \leq N \leq 300

S_{i,j} ( 1 \leq i, j \leq N ) is a lowercase English letter.

Input

Input is given from Standard Input in the following format:

N
S_{1,1}S_{1,2}..S_{1,N}
S_{2,1}S_{2,2}..S_{2,N}
:
S_{N,1}S_{N,2}..S_{N,N}

Output

Print the number of the ways to choose integers A and B ( 0 \leq A, B < N ) such that the second board is a good board.

Sample Input 1

2
ab
ca

Sample Output 1

2

For each pair of A and B, the second board will look as shown below:

The second board is a good board when (A,B) = (0,1) or (A,B) = (1,0), thus the answer is 2.

Sample Input 2

4
aaaa
aaaa
aaaa
aaaa

Sample Output 2

16

Every possible choice of A and B makes the second board good.

Sample Input 3

5
abcde
fghij
klmno
pqrst
uvwxy

Sample Output 3

0

No possible choice of A and B makes the second board good.

Solution in Rust (1.15.1) (judge verdict: Accepted)

use std::io::*;
use std::str::FromStr;

#[allow(dead_code)]
fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

fn main() {
    let n: usize = read();
    let mut field = vec![vec![]; n];
    for y in 0..n {
        field[y] = read::<String>()
            .chars()
            .map(|c| (c as u8 - 'a' as u8) as i64)
            .collect::<Vec<i64>>();
    }
    let modulo = (1i64 << 30) + 7;
    let base = 1e+9 as i64 + 7;
    let mut rolling_hash_x = vec![vec![0 as i64; n]; n];
    for y in 0..n {
        let mut hash = 0;
        let mut base2 = 1;
        for x in 0..n {
            hash = (hash * base + field[y][x]) % modulo;
            base2 = (base2 * base) % modulo;
        }
        for x in 0..n {
            rolling_hash_x[y][x] = hash;
            hash = (hash * base + field[y][x]) % modulo;
            hash = (hash - base2 * field[y][x] + modulo * modulo) % modulo;
        }
    }
    let mut rolling_hash_y = vec![vec![0 as i64; n]; n];
    for x in 0..n {
        let mut hash = 0;
        let mut base2 = 1;
        for y in 0..n {
            hash = (hash * base + field[y][x]) % modulo;
            base2 = (base2 * base) % modulo;
        }
        for y in 0..n {
            rolling_hash_y[y][x] = hash;
            hash = (hash * base + field[y][x]) % modulo;
            hash = (hash - base2 * field[y][x] + modulo * modulo) % modulo;
        }
    }
    let mut ans = 0;
    for dy in 0..n {
        'offset_loop: for dx in 0..n {
            for iter in 0..n {
                let ny = (iter + dy) % n;
                let nx = (iter + dx) % n;
                if rolling_hash_x[ny][dx] != rolling_hash_y[dy][nx] {
                    continue 'offset_loop;
                }
            }
            ans += 1;
        }
    }
    println!("{}", ans);
}