Problem: Snuke has a grid with H rows and W columns. The square at the i-th row and j-th column contains a character S_{i,j}.

He can perform the following two kinds of operation on the grid:

* Row-reverse: Reverse the order of the squares in a selected row.
* Column-reverse: Reverse the order of the squares in a selected column.



For example, reversing the 2-nd row followed by reversing the 4-th column will result as follows:

<image>

By performing these operations any number of times in any order, how many placements of characters on the grid can be obtained?

Constraints

* 1≦H,W≦200
* S_{i,j} is a lowercase English letter (`a`-`z`).

Input

The input is given from Standard Input in the following format:


H W
S_{1,1}S_{1,2}...S_{1,W}
S_{2,1}S_{2,2}...S_{2,W}
:
S_{H,1}S_{H,2}...S_{H,W}


Output

Print the number of placements of characters on the grid that can be obtained, modulo 1000000007 (=10^9+7).

Examples

Input

2 2
cf
cf


Output

6


Input

1 12
codefestival


Output

2

Solution (in CPP):

Solution:
#include<bits/stdc++.h>

using namespace std;

int ans = 1, N, M, ap[409];
char sir[409][409];
const int mod = 1e9 + 7;
vector < int > v[409];

int add (int x, int y) {int ans = x + y; if (ans >= mod) ans -= mod; return ans;}
int subtract (int x, int y) {if (x >= y) return x - y; return x - y + mod;}
int mul (int x, int y) {return 1LL * x * y % mod;}
void adto (int &x, int y) {x += y; if (x >= mod) x -= mod;}

int power (int a, int b)
{
    int p = 1;
    for (int i=0; (1<<i) <= b; i++)
    {
        if (b & (1 << i)) p = mul (p, a);
        a = mul (a, a);
    }
    return p;
}

void addEdge (int x, int y)
{
    v[x].push_back (y);
    v[y].push_back (x);
}

int sz = 0;
void dfs (int nod)
{
    sz ++, ap[nod] = 1;
    for (auto it : v[nod])
        if (ap[it] == 0)
            dfs (it);
}

int main ()
{
//freopen ("input", "r", stdin);
//freopen ("output", "w", stdout);

scanf ("%d %d\n", &N, &M);
for (int i=1; i<=N; i++)
    scanf ("%s", sir[i] + 1);
if (N == 1 || M == 1)
{
    int ans = 0;
    for (int i=1; i<=N; i++)
        for (int j=1; j<=M; j++)
            ans |= (sir[i][j] != sir[N + 1 - i][M + 1 - j]);
    printf ("%d\n", ans + 1);
    return 0;
}
int fac[10], inv[10];
inv[0] = fac[0] = 1;
for (int i=1; i<=4; i++)
    fac[i] = mul (fac[i - 1], i),
    inv[i] = power (fac[i], mod - 2);
for (int i=1; i<=N / 2; i++)
    for (int j=1; j<=M / 2; j++)
    {
        int c1 = sir[i][j], c2 = sir[N + 1 - i][j], c3 = sir[i][M + 1 - j], c4 = sir[N + 1 - i][M + 1 - j];
        map < char, int > mp;
        mp[c1] ++, mp[c2] ++, mp[c3] ++, mp[c4] ++;
        int curr = 24;
        for (auto it : mp)
            curr = mul (curr, inv[it.second]);
        if (curr != 24) ans = mul (ans, curr);
        else ans = mul (ans, 12), addEdge (i, N / 2 + j);
    }
if (N & 1)
{
    bool any = 0;
    for (int j=1; j<=M; j++)
        any |= (sir[N / 2 + 1][j] != sir[N / 2 + 1][M + 1 - j]);
    if (any) ans = mul (ans, 2);
}
if (M & 1)
{
    bool any = 0;
    for (int i=1; i<=N; i++)
        any |= (sir[i][M / 2 + 1] != sir[N + 1 - i][M / 2 + 1]);
    if (any) ans = mul (ans, 2);
}
int p2[N / 2 + M / 2 + 1];
p2[0] = 1;
for (int i=1; i<=N / 2 + M / 2; i++)
    p2[i] = add (p2[i - 1], p2[i - 1]);
for (int i=1; i<=N / 2 + M / 2; i++)
    if (ap[i] == 0)
    {
        sz = 0, dfs (i);
        ans = mul (ans, p2[sz - 1]);
    }
printf ("%d\n", ans);
return 0;
}