#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
using namespace std;

typedef long long ll;
const ll MOD = (ll)1e9 + 7;
ll mult(ll x, ll y)
{
	return (x * y) % MOD;
}

const int N = 500;
int n, m;
char s[N][N];
vector<int> g[N];
bool used[N];
ll f[5];

ll getCount(string p)
{
	sort(p.begin(), p.end());
	ll res = f[(int)p.size()];
	int l = 0;
	while(l < (int)p.size())
	{
		int r = l;
		while(r < (int)p.size() && p[l] == p[r]) r++;
		res /= f[r - l];
		l = r;
	}
	return res;
}

void dfs(int v)
{
	used[v] = 1;
	for (int u : g[v])
		if (!used[u])
			dfs(u);
	return;
}

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

	f[0] = 1;
	for (int i = 1; i < 5; i++)
		f[i] = f[i - 1] * i;

	scanf("%d%d", &n, &m);
	for (int i = 0; i < n; i++)
		scanf(" %s ", s[i]);
	ll ans = 1;
	for (int x = 0; x < n / 2; x++)
		for (int y = 0; y < m / 2; y++)
		{
			string p = "";
			p += s[x][y];
			p += s[n - 1 - x][y];
			p += s[x][m - 1 - y];
			p += s[n - 1 - x][m - 1 - y];
			ll z = getCount(p);
			if (z == 24)
			{
				z = 12;
				g[x].push_back(n + y);
				g[n + y].push_back(x);
			}
			ans = mult(ans, z);
		}
	if (n & 1)
	{
		bool ok = false;
		for (int y = 0; !ok && y < m / 2; y++)
			if (s[n / 2][y] != s[n / 2][m - 1 - y])
			{
				ok = true;
				ans = mult(ans, 2);
			}
	}
	if (m & 1)
	{
		bool ok = false;
		for (int x = 0; !ok && x < n / 2; x++)
			if (s[x][m / 2] != s[n - 1 - x][m / 2])
			{
				ok = true;
				ans = mult(ans, 2);
			}
	}
	int res = n + m;
	for (int i = 0; i < n + m; i++)
		if (!used[i])
		{
			res--;
			dfs(i);
		}
	for (int i = 0; i < res; i++)
		ans = mult(ans, 2);
	printf("%lld\n", ans);

	return 0;
}
### Prompt

Your task is to create a cpp solution to the following 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

### Response

```cpp
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
using namespace std;

typedef long long ll;
const ll MOD = (ll)1e9 + 7;
ll mult(ll x, ll y)
{
	return (x * y) % MOD;
}

const int N = 500;
int n, m;
char s[N][N];
vector<int> g[N];
bool used[N];
ll f[5];

ll getCount(string p)
{
	sort(p.begin(), p.end());
	ll res = f[(int)p.size()];
	int l = 0;
	while(l < (int)p.size())
	{
		int r = l;
		while(r < (int)p.size() && p[l] == p[r]) r++;
		res /= f[r - l];
		l = r;
	}
	return res;
}

void dfs(int v)
{
	used[v] = 1;
	for (int u : g[v])
		if (!used[u])
			dfs(u);
	return;
}

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

	f[0] = 1;
	for (int i = 1; i < 5; i++)
		f[i] = f[i - 1] * i;

	scanf("%d%d", &n, &m);
	for (int i = 0; i < n; i++)
		scanf(" %s ", s[i]);
	ll ans = 1;
	for (int x = 0; x < n / 2; x++)
		for (int y = 0; y < m / 2; y++)
		{
			string p = "";
			p += s[x][y];
			p += s[n - 1 - x][y];
			p += s[x][m - 1 - y];
			p += s[n - 1 - x][m - 1 - y];
			ll z = getCount(p);
			if (z == 24)
			{
				z = 12;
				g[x].push_back(n + y);
				g[n + y].push_back(x);
			}
			ans = mult(ans, z);
		}
	if (n & 1)
	{
		bool ok = false;
		for (int y = 0; !ok && y < m / 2; y++)
			if (s[n / 2][y] != s[n / 2][m - 1 - y])
			{
				ok = true;
				ans = mult(ans, 2);
			}
	}
	if (m & 1)
	{
		bool ok = false;
		for (int x = 0; !ok && x < n / 2; x++)
			if (s[x][m / 2] != s[n - 1 - x][m / 2])
			{
				ok = true;
				ans = mult(ans, 2);
			}
	}
	int res = n + m;
	for (int i = 0; i < n + m; i++)
		if (!used[i])
		{
			res--;
			dfs(i);
		}
	for (int i = 0; i < res; i++)
		ans = mult(ans, 2);
	printf("%lld\n", ans);

	return 0;
}
```