Language: C++

#include <iostream>
#include <algorithm>
#include <map>
#include <utility>
#define llint long long
#define mod 1000000007

using namespace std;
typedef pair<llint, llint> P;

struct UnionFind{
	int size;
	vector<int> parent;
	
	UnionFind(){}
	UnionFind(int size){
		this->size = size;
		parent.resize(size+1);
		init();
	}
	void init(){
		for(int i = 0; i <= size; i++) parent[i] = i;
	}
	int root(int i){
		if(parent[i] == i) return i;
		return parent[i] = root(parent[i]);
	}
	bool same(int i, int j){
		return root(i) == root(j);
	}
	void unite(int i, int j){
		int root_i = root(i), root_j = root(j);
		if(root_i == root_j) return;
		parent[root_i] = root_j;
	}
};

llint h, w;
char c[205][205];
bool b[205][205];
map<char, llint> mp;
map<llint, P> mp2;
UnionFind uf(405);

const int FACT_MAX = 15;
llint fact[FACT_MAX], fact_inv[FACT_MAX];

llint modpow(llint a, llint n)
{
	if(n == 0) return 1;
	if(n % 2){
		return ((a%mod) * (modpow(a, n-1)%mod)) % mod;
	}
	else{
		return modpow((a*a)%mod, n/2) % mod;
	}
}

void make_fact()
{
	llint val = 1;
	fact[0] = 1;
	for(int i = 1; i < FACT_MAX; i++){
		val *= i;
		val %= mod;
		fact[i] = val;
	}
	fact_inv[FACT_MAX-1] = modpow(fact[FACT_MAX-1], mod-2);
	for(int i = FACT_MAX-2; i >= 0; i--){
		fact_inv[i] = fact_inv[i+1] * (i+1) % mod;
	}
}

int main(void)
{
	make_fact();
	
	cin >> h >> w;
	for(int y = 1; y <= h; y++){
		for(int x = 1; x <= w; x++){
			cin >> c[x][y];
		}
	}
	
	llint ans = 1;
	if(h % 2){
		string s, t;
		for(int i = 1; i <= w; i++) s += c[i][h/2+1];
		t = s;
		reverse(t.begin(), t.end());
		if(s != t) ans *= 2;
		
		for(int y = h/2+1; y < h; y++){
			for(int x = 1; x <= w; x++){
				c[x][y] = c[x][y+1];
			}
		}
		h--;
	}
	if(w % 2){
		string s, t;
		for(int i = 1; i <= h; i++) s += c[w/2+1][i];
		t = s;
		reverse(t.begin(), t.end());
		if(s != t) ans *= 2;
		
		for(int x = w/2+1; x < w; x++){
			for(int y = 1; y <= h; y++){
				c[x][y] = c[x+1][y];
			}
		}
		w--;
	}
	
	if(h >= 1 && w >= 1){
		for(int y = 1; y <= h/2; y++){
			for(int x = 1; x <= w/2; x++){
				mp.clear();
				mp[c[x][y]]++;
				mp[c[w+1-x][y]]++;
				mp[c[w+1-x][h+1-y]]++;
				mp[c[x][h+1-y]]++;
				llint mul = fact[4];
				for(auto it = mp.begin(); it != mp.end(); it++) mul /= fact[it->second];
				if(mp.size() == 4) mul /= 2, b[x][y] = true;
				ans *= mul, ans %= mod;
			}
		}
	}
	
	h /= 2, w /= 2;
	for(int y = 1; y <= h; y++){
		for(int x = 1; x <= w; x++){
			if(b[x][y]) uf.unite(x, w+y);
		}
	}
	for(int x = 1; x <= w; x++) mp2[uf.root(x)].first++;
	for(int y = 1; y <= h; y++) mp2[uf.root(y+w)].second++;
	
	llint cnt = 0;
	for(auto it = mp2.begin(); it != mp2.end(); it++){
		cnt += it->second.first + it->second.second - 1;
	}
	ans *= modpow(2, cnt), ans %= mod;
	
	cout << ans << endl;
	
	return 0;
}

Compiler output:
a.cc:13:9: error: 'vector' does not name a type
   13 |         vector<int> parent;
      |         ^~~~~~
a.cc: In constructor 'UnionFind::UnionFind(int)':
a.cc:18:17: error: 'parent' was not declared in this scope
   18 |                 parent.resize(size+1);
      |                 ^~~~~~
a.cc: In member function 'void UnionFind::init()':
a.cc:22:48: error: 'parent' was not declared in this scope
   22 |                 for(int i = 0; i <= size; i++) parent[i] = i;
      |                                                ^~~~~~
a.cc: In member function 'int UnionFind::root(int)':
a.cc:25:20: error: 'parent' was not declared in this scope
   25 |                 if(parent[i] == i) return i;
      |                    ^~~~~~
a.cc:26:24: error: 'parent' was not declared in this scope
   26 |                 return parent[i] = root(parent[i]);
      |                        ^~~~~~
a.cc: In member function 'void UnionFind::unite(int, int)':
a.cc:34:17: error: 'parent' was not declared in this scope
   34 |                 parent[root_i] = root_j;
      |                 ^~~~~~