Problem:
Problem L
Wall Making Game
The game
Wall Making Game
, a two-player board game, is all the rage.
This game is played on an $H \times W$ board. Each cell of the board is one of
empty
,
marked
, or
wall
. At the beginning of the game, there is no wall on the board.
In this game, two players alternately move as follows:
A player chooses one of the empty cells (not marked and not wall). If the player can't choose a cell, he loses.
Towards each of the four directions (upper, lower, left, and right) from the chosen cell, the player changes cells (including the chosen cell) to walls until the player first reaches a wall or the outside of the board.
Note that marked cells cannot be chosen in step 1, but they can be changed to walls in step 2.
Fig.1 shows an example of a move in which a player chooses the cell at the third row and the fourth
column.
Fig.1: An example of a move in Wall Making Game.
Your task is to write a program that determines which player wins the game if the two players play optimally from a given initial board.
Input
The first line of the input consists of two integers $H$ and $W$ $(1 \leq H, W \leq 20)$, where $H$ and $W$ are the height and the width of the board respectively. The following $H$ lines represent the initial board. Each of the $H$ lines consists of $W$ characters.
The $j$-th character of the $i$-th line is '
.
' if the cell at the $j$-th column of the $i$-th row is empty, or '
X
' if the cell is marked.
Output
Print "
First
" (without the quotes) in a line if the first player wins the given game. Otherwise, print "
Second
" (also without the quotes) in a line.
Sample Input 1
2 2
..
..
Output for the Sample Input 1
Second
Sample Input 2
2 2
X.
..
Output for the Sample Input 2
First
Sample Input 3
4 5
X....
...X.
.....
.....
Output for the Sample Input 3
First

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define nn 22

int n,m;
char _map[nn][nn];
int dp[nn][nn][nn][nn];


int dfs(int x1,int y1,int x2,int y2){
	if(x1>x2 or y1>y2) return 0;
	if(dp[x1][y1][x2][y2]>-1) return dp[x1][y1][x2][y2];
	set<int> all;
	for(int i=x1;i<=x2;i++) {
		for(int j=y1;j<=y2;j++) if(_map[i][j]=='.'){
			int w=dfs(x1,y1,i-1,j-1)^dfs(x1,j+1,i-1,y2)^dfs(i+1,y1,x2,j-1)^dfs(i+1,j+1,x2,y2);
			all.insert(w);
		}
	}
	int res=0;
	while(all.count(res))res++;

	return dp[x1][y1][x2][y2]=res;
}

int main(){
	memset(dp,-1,sizeof dp);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%s",_map[i]+1);
	
	if(dfs(1,1,n,m)) puts("First");else puts("Second");	
	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 4460
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < (n); i++)
#define srep(i, s, t) for(int i = (s); i < (t); i++)
#define len(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
using i64 = long long;
using f64 = long double;
i64 floor_div(const i64 n, const i64 d) { assert(d != 0); return n / d - static_cast<i64>((n ^ d) <  0 && n % d != 0); }
i64  ceil_div(const i64 n, const i64 d) { assert(d != 0); return n / d + static_cast<i64>((n ^ d) >= 0 && n % d != 0); }

constexpr int M = 25;
int dp[M][M][M][M] = {};

int main() {
    cin.tie(0)->sync_with_stdio(0);
    rep(i, 21) rep(j, 21) rep(k, 21) rep(l, 21) dp[i][j][k][l] = -1;
    
    int H, W; cin >> H >> W;
    vector<string> S(H);
    for(auto& e : S) cin >> e;
    auto F = [&](auto&& F, int xL, int xR, int yL, int yR) -> int {
        if(not(xL <= xR and yL <= yR)) return 0;
        int& mex = dp[xL][xR][yL][yR];
        if(mex != -1) return mex;

        set<int> gs;
        for(int x = xL; x <= xR; x++) {
            for(int y = yL; y <= yR; y++) {
                if(S[x][y] == '.') {
                    int g = 0;
                    g ^= F(F, xL, x - 1, yL, y - 1);
                    g ^= F(F, x + 1, xR, yL, y - 1);
                    g ^= F(F, xL, x - 1, y + 1, yR);
                    g ^= F(F, x + 1, xR, y + 1, yR);
                    gs.insert(g);
                }
            }
        }
        mex = 0;
        while(gs.count(mex)) mex++;
        return mex;
    };
    cout << (F(F, 0, H - 1, 0, W - 1) != 0 ? "First" : "Second") << "\n";
}
accuracy: 1
time_ms: 70
memory_kb: 4616
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < (n); i++)
#define srep(i, s, t) for(int i = (s); i < (t); i++)
#define len(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
using i64 = long long;
using f64 = long double;
i64 floor_div(const i64 n, const i64 d) { assert(d != 0); return n / d - static_cast<i64>((n ^ d) <  0 && n % d != 0); }
i64  ceil_div(const i64 n, const i64 d) { assert(d != 0); return n / d + static_cast<i64>((n ^ d) >= 0 && n % d != 0); }

constexpr int M = 25;
int dp[M][M][M][M] = {};

int main() {
    cin.tie(0)->sync_with_stdio(0);
    rep(i, 21) rep(j, 21) rep(k, 21) rep(l, 21) dp[i][j][k][l] = -1;
    
    int H, W; cin >> H >> W;
    vector<string> S(H);
    for(auto& e : S) cin >> e;
    auto F = [&](auto&& F, int xL, int xR, int yL, int yR) -> int {
        int& mex = dp[xL][xR][yL][yR];
        if(mex != -1) return mex;

        set<int> gs;
        for(int x = xL; x <= xR; x++) {
            for(int y = yL; y <= yR; y++) {
                if(S[x][y] == '.') {
                    int g = 0;
                    g ^= F(F, xL, x - 1, yL, y - 1);
                    g ^= F(F, x + 1, xR, yL, y - 1);
                    g ^= F(F, xL, x - 1, y + 1, yR);
                    g ^= F(F, x + 1, xR, y + 1, yR);
                    gs.insert(g);
                }
            }
        }
        mex = 0;
        while(gs.count(mex)) mex++;
        return mex;
    };
    cout << (F(F, 0, H - 1, 0, W - 1) != 0 ? "First" : "Second") << "\n";
}
accuracy: 0.8035714285714286
time_ms: 70
memory_kb: 4652
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < (n); i++)
#define srep(i, s, t) for(int i = (s); i < (t); i++)
#define len(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
using i64 = long long;
using f64 = long double;
i64 floor_div(const i64 n, const i64 d) { assert(d != 0); return n / d - static_cast<i64>((n ^ d) <  0 && n % d != 0); }
i64  ceil_div(const i64 n, const i64 d) { assert(d != 0); return n / d + static_cast<i64>((n ^ d) >= 0 && n % d != 0); }

int dp[21][21][21][21] = {};

int main() {
    cin.tie(0)->sync_with_stdio(0);
    rep(i, 21) rep(j, 21) rep(k, 21) rep(l, 21) dp[i][j][k][l] = -1;
    
    int H, W; cin >> H >> W;
    vector<string> S(H);
    for(auto& e : S) cin >> e;
    auto F = [&](auto&& F, int xL, int xR, int yL, int yR) -> int {
        int& mex = dp[xL][xR][yL][yR];
        if(mex != -1) return mex;

        set<int> gs;
        for(int x = xL; x <= xR; x++) {
            for(int y = yL; y <= yR; y++) {
                if(S[x][y] == '.') {
                    int g = 0;
                    g ^= F(F, xL, x - 1, yL, y - 1);
                    g ^= F(F, x + 1, xR, yL, y - 1);
                    g ^= F(F, xL, x - 1, y + 1, yR);
                    g ^= F(F, x + 1, xR, y + 1, yR);
                    gs.insert(g);
                }
            }
        }
        mex = 0;
        while(gs.count(mex)) mex++;
        return mex;
    };
    cout << (F(F, 0, H - 1, 0, W - 1) != 0 ? "First" : "Second") << "\n";
}
accuracy: 0.7946428571428571
time_ms: 70
memory_kb: 4232
final_rank: 20

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

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

int main() {
    int N, M;
    cin >> N >> M;
    vector<vector<bool>> B(N,vector<bool>(M));
    rep(i,0,N) {
        string S;
        cin >> S;
        rep(j,0,M) {
            if (S[j] == 'X') B[i][j] = true;
            else B[i][j] = false;
        }
    }
    vector DP(N+1,vector(N+1,vector(M+1,vector<int>(M+1,-1))));
    auto DFS = [&](auto&& self, int LX, int RX, int LY, int RY) -> int {
        if (LX == RX || LY == RY) return 0;
        if (DP[LX][RX][LY][RY] >= 0) return DP[LX][RX][LY][RY];
        set<int> st;
        rep(i,LX,RX) {
            rep(j,LY,RY) {
                if (B[i][j]) continue;
                st.insert(self(self,LX,i,LY,j) ^ self(self,i+1,RX,LY,j) ^ self(self,LX,i,j+1,RY) ^ self(self,i+1,RX,j+1,RY));
            }
        }
        int Cur = 0;
        while(1) {
            if (!st.count(Cur)) break;
            Cur++;
        }
        return DP[LX][RX][LY][RY] = Cur;
    };
    cout << (DFS(DFS,0,N,0,M) == 0 ? "Second" : "First") << endl;
}
accuracy: 1
time_ms: 80
memory_kb: 4592
final_rank: 13

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

int H,W;
vector<string> S;
map<pair<pair<int,int>,pair<int,int>>,int> GR;
int gr(int L,int R,int U,int D){
    if(L>=R||U>=D)return 0;
    if(GR.count({{L,R},{U,D}}))return GR[{{L,R},{U,D}}];
    set<int> ST;
    for(int w=L;w<R;w++){
        for(int h=U;h<D;h++){
            if(S[h][w]=='X')continue;
            int X=0;
            X^=gr(L,w,U,h);
            X^=gr(L,w,h+1,D);
            X^=gr(w+1,R,U,h);
            X^=gr(w+1,R,h+1,D);
            ST.insert(X);
        }
    }
    for(int i=0;i<10000;i++){
        if(!ST.count(i)){
            GR[{{L,R},{U,D}}]=i;
            // cout<<L<<" "<<R<<" "<<U<<" "<<D<<" "<<i<<endl;
            return i;
        }
    }
    return -1;
}

int main() {

    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    cin>>H>>W;
    S.resize(H);
    for(int h=0;h<H;h++)cin>>S[h];
    int g=gr(0,W,0,H);
    cout<<(g==0?"Second":"First")<<"\n";
    
}
accuracy: 1
time_ms: 860
memory_kb: 6176
final_rank: 16

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int H, W;
char c[22][22];
int dp[22][22][22][22];

int GetMex(vector<int> vec) {
	vec.push_back(-1);
	vec.push_back(100000000);
	sort(vec.begin(), vec.end());
	for (int i = 0; i < vec.size() - 1; i++) {
		if (vec[i + 1] - vec[i] >= 2) return vec[i] + 1;
	}
	return -1;
}

int dfs(int lx, int ly, int rx, int ry) {
	if (lx > rx || ly > ry) return 0;
	if (dp[lx][ly][rx][ry] != -1) return dp[lx][ly][rx][ry];

	vector<int> cand;
	for (int i = lx; i <= rx; i++) {
		for (int j = ly; j <= ry; j++) {
			if (c[i][j] == 'X') continue;
			int v1 = dfs(   lx,    ly, i - 1, j - 1);
			int v2 = dfs(   lx, j + 1, i - 1,    ry);
			int v3 = dfs(i + 1,    ly,    rx, j - 1);
			int v4 = dfs(i + 1, j + 1,    rx,    ry);
			cand.push_back(v1 ^ v2 ^ v3 ^ v4);
		}
	}
	int val = GetMex(cand);
	dp[lx][ly][rx][ry] = val;
	return val;
}

int main() {
	// Step 1. Input
	cin >> H >> W;
	for (int i = 1; i <= H; i++) {
		for (int j = 1; j <= W; j++) cin >> c[i][j];
	}

	// Step 2. DP Init
	for (int i = 1; i <= H; i++) {
		for (int j = 1; j <= W; j++) {
			for (int k = 1; k <= H; k++) {
				for (int l = 1; l <= W; l++) dp[i][j][k][l] = -1;
			}
		}
	}

	// Step 3. DP & Output
	int Answer = dfs(1, 1, H, W);
	if (Answer == 0) cout << "Second" << endl;
	else cout << "First" << endl;
	return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 4236
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;

constexpr int N = 30;
int memo[N][N][N][N];
vector<string> s(N);
int h, w;

int dfs(int si, int sj, int ti, int tj) {
        if (memo[si][sj][ti][tj] != -1) return memo[si][sj][ti][tj];
        if (ti - si < 1) return 0;
        if (tj - sj < 1) return 0;
        std::vector<bool> used(N * N, false);        
        for (int i = si; i < ti; i++) {
                for (int j = sj; j < tj; j++) {
                        if (s[i][j] == 'X') continue;
                        int ans = 0;
                        ans ^= dfs(si, sj, i, j);
                        ans ^= dfs(si, j + 1, i, tj);
                        ans ^= dfs(i + 1, sj, ti, j);
                        ans ^= dfs(i + 1, j + 1, ti, tj);
                        if (ans < N * N) used[ans] = true;
                }
        }
        memo[si][sj][ti][tj] = N * N;
        for (int i = 0; i < N * N; i++) {
                if (used[i]) continue;
                memo[si][sj][ti][tj] = i;
                break;
        }
        return memo[si][sj][ti][tj];
}

int main() {
        std::cin >> h >> w;
        for (int i = 0; i < h; i++) {
                std::cin >> s[i];
        }
        for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                        for (int k = 0; k < N; k++) {
                                for (int l = 0; l < N; l++) {
                                        memo[i][j][k][l] = -1;
                                }
                        }
                }
        }
        int ans = dfs(0, 0, h, w);
        if (ans > 0) {
                std::cout << "First" << '\n';
        } else {
                std::cout << "Second" << '\n';
        }
}
accuracy: 1
time_ms: 30
memory_kb: 6612
final_rank: 15

code_snippet: #include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#define _GLIBCXX_DEBUG
using namespace std;
using std::cout;
using std::cin;
using std::endl;
using ll=long long;
using ld=long double;
ll ILL=2167167167167167167;
const int INF=2100000000;
const ll mod=1e9+9;
#define rep(i,a) for (int i=0;i<a;i++)
#define all(p) p.begin(),p.end()
template<class T> using _pq = priority_queue<T, vector<T>, greater<T>>;
template<class T> ll LB(vector<T> &v,T a){return lower_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> ll UB(vector<T> &v,T a){return upper_bound(v.begin(),v.end(),a)-v.begin();}
template<class T> bool chmin(T &a,const T &b){if(a>b){a=b;return 1;}else return 0;}
template<class T> bool chmax(T &a,const T &b){if(a<b){a=b;return 1;}else return 0;}
template<class T> void So(vector<T> &v) {sort(v.begin(),v.end());}
template<class T> void Sore(vector<T> &v) {sort(v.begin(),v.end(),[](T x,T y){return x>y;});}
void yneos(bool a){if(a) cout<<"Yes\n"; else cout<<"No\n";}
template<class T> void vec_out(vector<T> &p){for(int i=0;i<(int)(p.size());i++){if(i) cout<<" ";cout<<p[i];}cout<<"\n";}


void solve();


// oddloop
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	solve();
}

void solve(){
	int H,W;
	cin>>H>>W;
	vector<vector<char>> p(H,vector<char>(W));
	rep(i,H) rep(j,W){
		cin>>p[i][j];
	}
	int dp[H+1][H+1][W+1][W+1];
	set<int> s;
	rep(d,H+1) for(int u=d;u>=0;u--) rep(r,W+1) for(int l=r;l>=0;l--){
		if(d==u||l==r) dp[u][d][l][r]=0;
		else if(d-u==1&&r-l==1){
			if(p[u][l]=='.') dp[u][d][l][r]=1;
			else dp[u][d][l][r]=0;
		}else{
			s.clear();
			for(int i=u;i<d;i++) for(int j=l;j<r;j++){
				if(p[i][j]=='.'){
					int tmp=0;
					tmp^=dp[u][i][l][j];
					tmp^=dp[u][i][j+1][r];
					tmp^=dp[i+1][d][l][j];
					tmp^=dp[i+1][d][j+1][r];
					s.insert(tmp);
				}
			}
			rep(i,400){
				if(!s.count(i)){
					dp[u][d][l][r]=i;
					break;
				}
			}
		}
		//cout<<u<<" "<<d<<" "<<l<<" "<<r<<"\n"<<dp[u][d][l][r]<<"\n";
	}
	if(dp[0][H][0][W]==0) cout<<"Second\n";
	else cout<<"First\n";
}
accuracy: 1
time_ms: 50
memory_kb: 3944
final_rank: 1

code_snippet: #include "bits/stdc++.h"
using namespace std;

typedef string::const_iterator State;
#define eps 1e-8L
#define MAX_MOD 1000000007LL
#define GYAKU 500000004LL
#define MOD 998244353LL
#define pb push_back
#define mp make_pair
typedef long long ll;
typedef long double ld;
#define REP(a, b) for (long long(a) = 0; (a) < (b); ++(a))
#define ALL(x) (x).begin(), (x).end()

#define int long long

int dp[20][20][20][20];
int cnt[20][20];

int nim(int l_h, int l_w, int r_h, int r_w)
{
  if (r_h < l_h or r_w < l_w)
    return 0;
  if (dp[l_h][l_w][r_h][r_w] == -1)
  {
    set<int> inputs;
    for (int i = l_h; i <= r_h; ++i)
    {
      for (int j = l_w; j <= r_w; ++j)
      {
        if (cnt[i][j] == 0)
        {
          inputs.insert(nim(l_h, l_w, i - 1, j - 1) ^ nim(i + 1, l_w, r_h, j - 1) ^ nim(i + 1, j + 1, r_h, r_w) ^ nim(l_h, j + 1, i - 1, r_w));
        }
      }
    }

    for (int i = 0;; ++i)
    {
      if (inputs.count(i) == 0)
      {
        dp[l_h][l_w][r_h][r_w] = i;
        break;
      }
    }
  }
  return dp[l_h][l_w][r_h][r_w];
}

void solve()
{
  int h, w;
  cin >> h >> w;
  REP(i, h)
  {
    string s;
    cin >> s;
    REP(q, w)
    {
      if (s[q] == 'X')
      {
        cnt[i][q] = 1;
      }
    }
  }

  REP(i, h)
  {
    REP(q, w)
    {
      REP(t, h)
      {
        REP(p, w)
        {
          dp[i][q][t][p] = -1;
        }
      }
    }
  }
  if(nim(0, 0, h - 1, w - 1)){
    cout << "First" << endl;
  }else{
    cout << "Second" << endl;
  }
}
#undef int

// generated by oj-template v4.7.2
// (https://github.com/online-judge-tools/template-generator)
int main()
{
  // Fasterize input/output script
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(100);
  // scanf/printf user should delete this fasterize input/output script

  int t = 1;
  // cin >> t; // comment out if solving multi testcase
  for (int testCase = 1; testCase <= t; ++testCase)
  {
    solve();
  }
  return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 4712
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;

using ll = long long;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define ALL(x) x.begin(), x.end()

int H, W;
int grundy[22][22][22][22];
string g[22];

int rec(int h1, int h2, int w1, int w2) {
    if (grundy[h1][h2][w1][w2] != -1) return grundy[h1][h2][w1][w2];
    if (h1 == h2 || w1 == w2) return 0;
    set<int> s;
    for (int i = h1; i < h2; i++) {
        for (int j = w1; j < w2; j++) {
            if (g[i][j] == 'X') continue;
            int c = 0;
            c ^= rec(h1, i, w1, j);
            c ^= rec(h1, i, j + 1, w2);
            c ^= rec(i + 1, h2, w1, j);
            c ^= rec(i + 1, h2, j + 1, w2);
            s.insert(c);
        }
    }
    int g = 0;
    while (s.count(g) != 0) g++;
    return grundy[h1][h2][w1][w2] = g;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> H >> W;
    rep(i, H) cin >> g[i];
    rep(h1, 22) rep(h2, 22) rep(w1, 22) rep(w2, 22) grundy[h1][h2][w1][w2] = -1;
    int a = rec(0, H, 0, W);
    cout << (a ? "First" : "Second") << "\n";
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 4420
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
// #pragma GCC target("arch=skylake-avx512")
// #include <atcoder/all>
// using namespace atcoder;
// #define NDEBUG

#pragma region template
// Define
using ll = long long;
using ull = unsigned long long;
using ld = long double;
template <class T> using pvector = vector<pair<T, T>>;
template <class T> using rpriority_queue = priority_queue<T, vector<T>, greater<T>>;
constexpr const ll dx[4] = {1, 0, -1, 0};
constexpr const ll dy[4] = {0, 1, 0, -1};
constexpr const ll MOD = 1e9 + 7;
constexpr const ll mod = 998244353;
constexpr const ll INF = 1LL << 60;
constexpr const ll inf = 1 << 30;
constexpr const char rt = '\n';
constexpr const char sp = ' ';
#define rt(i, n) (i == (ll) (n) -1 ? rt : sp)
#define len(x) ((ll) (x).size())
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define mp make_pair
#define mt make_tuple
#define pb push_back
#define eb emplace_back
#define ifn(x) if (not(x))
#define elif else if
#define elifn else ifn
#define fi first
#define se second
#define uniq(x) (sort(all(x)), (x).erase(unique(all(x)), (x).end()))
#define bis(x, y) ((ll) (lower_bound(all(x), y) - (x).begin()))

using graph = vector<vector<ll>>;
template <class T> using wgraph = vector<vector<pair<ll, T>>>;
bool __DIRECTED__ = true;
bool __ZERO_INDEXED__ = false;
istream &operator>>(istream &is, graph &g) {
    ll a, b;
    is >> a >> b;
    if (__ZERO_INDEXED__ == false) a--, b--;
    g[a].pb(b);
    if (__DIRECTED__ == false) g[b].pb(a);
    return is;
}
template <class T> istream &operator>>(istream &is, wgraph<T> &g) {
    ll a, b;
    T c;
    is >> a >> b >> c;
    if (__ZERO_INDEXED__ == false) a--, b--;
    g[a].pb({b, c});
    if (__DIRECTED__ == false) g[b].pb({a, c});
    return is;
}

template <class T> bool chmax(T &a, const T &b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T> bool chmin(T &a, const T &b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}

// Debug
#ifdef NDEBUG
#define debug(...)
#define dumpi(a, h, w)
#define vdumpi(a, n)
#define dump(a, h, w)
#define vdump(a, n)
#else
#define debug(...)                                                                                 \
    {                                                                                              \
        cerr << __LINE__ << ": " << #__VA_ARGS__ << " = ";                                         \
        for (auto &&__i : {__VA_ARGS__}) cerr << "[" << __i << "] ";                               \
        cerr << rt;                                                                                \
    }

#define dumpi(a, h, w)                                                                             \
    {                                                                                              \
        cerr << __LINE__ << ": " << #a << " = [" << rt;                                            \
        rep(__i, h) {                                                                              \
            if (__i) cerr << ",\n";                                                                \
            cerr << "[";                                                                           \
            rep(__j, w) {                                                                          \
                if (__j) cerr << ", ";                                                             \
                if (abs(a[__i][__j]) >= INF / 2 and a[__i][__j] <= -INF / 2) cerr << '-';          \
                if (abs(a[__i][__j]) >= INF / 2) cerr << "∞";                                      \
                else                                                                               \
                    cerr << a[__i][__j];                                                           \
            }                                                                                      \
            cerr << "]";                                                                           \
        }                                                                                          \
        cerr << "\n]" << rt;                                                                       \
    }

#define vdumpi(a, n)                                                                               \
    {                                                                                              \
        cerr << __LINE__ << ": " << #a << " = [";                                                  \
        rep(__i, n) {                                                                              \
            if (__i) cerr << ", ";                                                                 \
            if (abs(a[__i]) >= INF / 2 and a[__i] <= -INF / 2) cerr << '-';                        \
            if (abs(a[__i]) >= INF / 2) cerr << "∞";                                               \
            else                                                                                   \
                cerr << a[__i];                                                                    \
        }                                                                                          \
        cerr << "]" << rt;                                                                         \
    }

#define dump(a, h, w)                                                                              \
    {                                                                                              \
        cerr << __LINE__ << ": " << #a << " = [" << rt;                                            \
        rep(__i, h) {                                                                              \
            if (__i) cerr << ",\n";                                                                \
            cerr << "[";                                                                           \
            rep(__j, w) {                                                                          \
                if (__j) cerr << ", ";                                                             \
                cerr << a[__i][__j];                                                               \
            }                                                                                      \
            cerr << "]";                                                                           \
        }                                                                                          \
        cerr << "\n]" << rt;                                                                       \
    }

#define vdump(a, n)                                                                                \
    {                                                                                              \
        cerr << __LINE__ << ": " << #a << " = [";                                                  \
        rep(__i, n) {                                                                              \
            if (__i) cerr << ", ";                                                                 \
            cerr << a[__i];                                                                        \
        }                                                                                          \
        cerr << "]" << rt;                                                                         \
    }
#endif

template <class S, class T> istream &operator>>(istream &is, pair<S, T> &p) {
    is >> p.first >> p.second;
    return is;
}
template <class S, class T> ostream &operator<<(ostream &os, const pair<S, T> &p) {
    os << p.first << ' ' << p.second;
    return os;
}

// Loop
#define inc(i, a, n) for (ll i = (a), _##i = (n); i <= _##i; ++i)
#define dec(i, a, n) for (ll i = (a), _##i = (n); i >= _##i; --i)
#define rep(i, n) for (ll i = 0, _##i = (n); i < _##i; ++i)
#define each(i, a) for (auto &&i : a)

// Stream
#define fout(n) cout << fixed << setprecision(n)
struct io {
    io() { cin.tie(nullptr), ios::sync_with_stdio(false); }
} io;

// Speed
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native")
#pragma GCC optimize("Ofast,unroll-loops")

// Math
inline constexpr ll gcd(const ll a, const ll b) { return b ? gcd(b, a % b) : a; }
inline constexpr ll lcm(const ll a, const ll b) { return a / gcd(a, b) * b; }

inline constexpr ll modulo(const ll n, const ll m = MOD) {
    ll k = n % m;
    return k + m * (k < 0);
}
inline constexpr ll chmod(ll &n, const ll m = MOD) {
    n %= m;
    return n += m * (n < 0);
}
inline constexpr ll mpow(ll a, ll n, const ll m = MOD) {
    ll r = 1;
    rep(i, 64) {
        if (n & (1LL << i)) r *= a;
        chmod(r, m);
        a *= a;
        chmod(a, m);
    }
    return r;
}
inline ll inv(const ll n, const ll m = MOD) {
    ll a = n, b = m, x = 1, y = 0;
    while (b) {
        ll t = a / b;
        a -= t * b;
        swap(a, b);
        x -= t * y;
        swap(x, y);
    }
    return modulo(x, m);
}
unsigned long long binary_gcd(unsigned long long x, unsigned long long y) {
    if (!x | !y) return x | y;
    unsigned long long cx = __builtin_ctzll(x), cy = __builtin_ctzll(y);
    x >>= cx, y >>= cy;
    while (x ^ y) {
        if (x > y) {
            x = (x - y) >> __builtin_ctzll(x ^ y);
        } else {
            y = (y - x) >> __builtin_ctzll(x ^ y);
        }
    }
    return x << min(cx, cy);
}

inline long long binary_gcd(long long x, long long y) {
    return binary_gcd((unsigned long long) (abs(x)), (unsigned long long) (abs(y)));
}

#define codeforces                                                                                 \
    ll testcases;                                                                                  \
    cin >> testcases;                                                                              \
    rep(testcase, testcases)
#define gcj(s) cout << s << testcase + 1 << ": "

#pragma endregion

signed main() {
    ll n, m;
    cin >> n >> m;
    string s[n];
    rep(i, n) cin >> s[i];
    map<tuple<ll, ll, ll, ll>, ll> mp;
    function<ll(ll, ll, ll, ll)> win = [&](ll l, ll r, ll u, ll d) {
        if (u > d or l > r) return 0LL;
        if (mp.count({l, r, u, d})) return mp[{l, r, u, d}];

        vector<ll> grandy;
        inc(i, u, d) {
            inc(j, l, r) {
                if (s[i][j] == 'X') continue;
                ll g = 0;
                g ^= win(l, j - 1, u, i - 1);
                g ^= win(l, j - 1, i + 1, d);
                g ^= win(j + 1, r, u, i - 1);
                g ^= win(j + 1, r, i + 1, d);
                grandy.push_back(g);
            }
        }
        sort(all(grandy));
        ll t = 0, num = 0;
        while (t < grandy.size() and grandy[t] <= num) {
            if (grandy[t] == num) num++;
            t++;
        }
        return mp[{l, r, u, d}] = num;
    };

    cout << (win(0, m - 1, 0, n - 1) ? "First" : "Second") << rt;
}
accuracy: 1
time_ms: 1020
memory_kb: 6784
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)

int H, W;
vector<string> board;
map<tuple<int, int, int, int>, int> memo;

int dfs(int t, int b, int l, int r) {
    if (t == b || l == r) return 0;
    if (memo.count({t, b, l, r})) return memo[{t, b, l, r}];
    set<int> st;
    rep(i, t, b) rep(j, l, r) {
        if (board[i][j] == '.') {
            int x = dfs(t,i,l,j) ^ dfs(t,i,j+1,r) ^ dfs(i+1,b,l,j) ^ dfs(i+1,b,j+1,r);
            st.insert(x);
        }
    }
    int y = 0;
    while (st.count(y)) ++y;
    return memo[{t,b,l,r}] = y;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    cin >> H >> W;
    board.resize(H);
    for (auto& x : board) cin >> x;
    cout << (dfs(0, H, 0, W) ? "First" : "Second") << "\n";
}
accuracy: 1
time_ms: 970
memory_kb: 6084
final_rank: 17

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
//using namespace atcoder;
#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")
using namespace std;
 
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<int, int> pii;
typedef pair<long long, long long> PLL;
typedef pair<int, PII> TIII;
 
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
 
 
#define FOR(i, s, n) for (int i = s; i < (int)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define rep(i, a, b) for (int i = a; i < (b); ++i)
#define trav(a, x) for (auto &a : x)
#define all(x) x.begin(), x.end()
 
#define MOD 1000000007
 
template<class T1, class T2> inline bool chmax(T1 &a, T2 b) {if (a < b) {a = b; return true;} return false;}
template<class T1, class T2> inline bool chmin(T1 &a, T2 b) {if (a > b) {a = b; return true;} return false;}
const double EPS = 1e-8, PI = acos(-1);
const double pi = 3.141592653589793238462643383279;
//ここから編集    
typedef string::const_iterator State;
ll GCD(ll a, ll b){
  return (b==0)?a:GCD(b, a%b);
}
ll LCM(ll a, ll b){
  return a/GCD(a, b) * b;
}
template< int mod >
struct ModInt {
  int x;
 
  ModInt() : x(0) {}
 
  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
 
  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }
 
  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
 
  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }
 
  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }
 
  ModInt operator-() const { return ModInt(-x); }
 
  ModInt operator+(const ModInt &p) const { return ModInt(*this) += p; }
 
  ModInt operator-(const ModInt &p) const { return ModInt(*this) -= p; }
 
  ModInt operator*(const ModInt &p) const { return ModInt(*this) *= p; }
 
  ModInt operator/(const ModInt &p) const { return ModInt(*this) /= p; }
 
  bool operator==(const ModInt &p) const { return x == p.x; }
 
  bool operator!=(const ModInt &p) const { return x != p.x; }
 
  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
 
  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while(n > 0) {
      if(n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }
 
  friend ostream &operator<<(ostream &os, const ModInt &p) {
    return os << p.x;
  }
 
  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }
 
  static int get_mod() { return mod; }
};
 
using modint = ModInt< 1000000007 >;
template< typename T >
struct Combination {
  vector< T > _fact, _rfact, _inv;
 
  Combination(int sz) : _fact(sz + 1), _rfact(sz + 1), _inv(sz + 1) {
    _fact[0] = _rfact[sz] = _inv[0] = 1;
    for(int i = 1; i <= sz; i++) _fact[i] = _fact[i - 1] * i;
    _rfact[sz] /= _fact[sz];
    for(int i = sz - 1; i >= 0; i--) _rfact[i] = _rfact[i + 1] * (i + 1);
    for(int i = 1; i <= sz; i++) _inv[i] = _rfact[i] * _fact[i - 1];
  }
 
  inline T fact(int k) const { return _fact[k]; }
 
  inline T rfact(int k) const { return _rfact[k]; }
 
  inline T inv(int k) const { return _inv[k]; }
 
  T P(int n, int r) const {
    if(r < 0 || n < r) return 0;
    return fact(n) * rfact(n - r);
  }
 
  T C(int p, int q) const {
    if(q < 0 || p < q) return 0;
    return fact(p) * rfact(q) * rfact(p - q);
  }
 
  T H(int n, int r) const {
    if(n < 0 || r < 0) return (0);
    return r == 0 ? 1 : C(n + r - 1, r);
  }
};
 
ll modpow(ll x, ll n, ll mod) {
  ll res = 1;
  x %= mod;
  if(x == 0) return 0;
  while(n) {
    if(n&1) res = (res * x) % mod;
    x = (x * x) % mod;
    n >>= 1;
  }
  return res;
} 
inline long long mod(long long a, long long m) {
    return (a % m + m) % m;
}
template<typename T> 
struct BIT{
  int N;
  std::vector<T> node;
  BIT(){}
  BIT(int n){
    N = n;
    node.resize(N+10);
  }
  void build(int n) {
    N = n;
    node.resize(N+10);
  }
  /* a: 1-indexed */
  void add(int a, T x){
    for(int i=a; i<(int)node.size(); i += i & -i) node[i] += x;
  }

  /* [1, a] */
  T sum(int a){
    T res = 0;
    for(int x=a; x>0; x -= x & -x) res += node[x];
    return res;
  }

  /* [l, r] */
  T rangesum(int l, int r){
    return sum(r) - sum(l-1);
  }

  /* 
    a1+a2+...+aw >= valとなるような最小のwを返す
    @verify https://codeforces.com/contest/992/problem/E
  */
  int lower_bound(T val) {
    if(val < 0) return 0;

    int res = 0;
    int n = 1; 
    while (n < N) n *= 2;

    T tv=0;
    for (int k = n; k > 0; k /= 2) {
      if(res + k < N && node[res + k] < val){
        val -= node[res+k];
        res += k;
      }
    }
    return res+1; 
  }
};
struct UnionFind{
  std::vector<int> par;
  std::vector<int> siz;

  UnionFind(int sz_): par(sz_), siz(sz_) {
    for(int i=0; i<sz_; ++i) par[i] = i, siz[i] = 1;
  }

  void init(int sz_){
    par.resize(sz_);
    siz.resize(sz_);
    for(int i=0; i<sz_; ++i) par[i] = i, siz[i] = 1;
  }

  int root(int x){
    if(x == par[x]) return x;
    return par[x] = root(par[x]);
  }

  bool merge(int x, int y){
    x = root(x), y = root(y);
    if(x == y) return false;
    if(siz[x] < siz[y]) std::swap(x, y);
    siz[x] += siz[y];
    par[y] = x;
    return true;
  }

  bool issame(int x, int y){
    return root(x) == root(y);
  }

  int size(int x){
    return siz[root(x)];
  }
};
struct RollingHash{

    using ull = unsigned long long;
    const ull mod = (1ULL << 61) - 1;
    const ull MASK30 = (1ULL << 30) - 1;
    const ull MASK31 = (1ULL << 31) - 1;

    const ull MASK61 = mod;

    ull base;
    int n;
    vector<ull> hash, pow;

    RollingHash(const string &s)
    {
        random_device rnd;
        mt19937_64 mt(rnd());
        base = 1001;
        
        n = (int)s.size();
        hash.assign(n+1, 0);
        pow.assign(n+1, 1);
        
        for(int i=0; i<n; i++){
            hash[i+1] = calc_mod(mul(hash[i], base) + s[i]);
            pow[i+1] = calc_mod(mul(pow[i], base));
        }
    }

    ull calc_mod(ull x){
        ull xu = x >> 61;
        ull xd = x & MASK61;
        ull res = xu + xd;
        if(res >= mod) res -= mod;
        return res;
    }

    ull mul(ull a, ull b){
        ull au = a >> 31;
        ull ad = a & MASK31;
        ull bu = b >> 31;
        ull bd = b & MASK31;
        ull mid = ad * bu + au * bd;
        ull midu = mid >> 30;
        ull midd = mid & MASK30;
        return calc_mod(au * bu * 2 + midu + (midd << 31) + ad * bd);
    }

    //[l,r)のハッシュ値
    inline ull get(int l, int r){
        ull res = calc_mod(hash[r] + mod*3-mul(hash[l], pow[r-l]));
        return res;
    }
    //string tのハッシュ値
    inline ull get(string t){
        ull res = 0;
        for(int i=0; i<t.size(); i++){
            res = calc_mod(mul(res, base)+t[i]);
        }
        return res;
    }
    //string s中のtの数をカウント
    inline int count(string t) {
        if(t.size() > n) return 0;
        auto hs = get(t);
        int res = 0;
        for(int i=0; i<n-t.size()+1; i++){
            if(get(i, i+t.size()) == hs) res++; 
        }
        return res;
    }

    /* 
        concat 
        @verify https://codeforces.com/problemset/problem/514/C
    */
    inline ull concat(ull h1, ull h2, int h2len){
      return calc_mod(h2 + mul(h1, pow[h2len]));
    }

    // LCPを求める S[a:] T[b:]
    inline int LCP(int a, int b){
        int len = min((int)hash.size()-a, (int)hash.size()-b);
        
        int lb = -1, ub = len;
        while(ub-lb>1){
            int mid = (lb+ub)/2;

            if(get(a, a+mid) == get(b, b+mid)) lb = mid;
            else ub = mid;
        }
        return lb;
    }
};
vector<string> f(22);
int dp[22][22][22][22];
int rec(int sy, int sx, int gy, int gx) {
  if(sy > gy || sx > gx) return 0;
  if(dp[sy][sx][gy][gx] != -1) return dp[sy][sx][gy][gx];
  set<int> st;
  for(int i=sy; i<=gy; i++) {
    for(int j=sx; j<=gx; j++) {
      if(f[i][j] == '.') {
        int t = rec(sy, sx, i-1, j-1) ^ rec(sy, j+1, i-1, gx) ^ rec(i+1, sx, gy, j-1) ^ rec(i+1, j+1, gy, gx);
        st.insert(t);
      }
    }
  }
  int res = 0;
  while(st.count(res)) res++;
  return dp[sy][sx][gy][gx] = res;
}
int main() {  
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(12);
  
  int h, w; cin >> h >> w;
  REP(i,h) cin >> f[i];
  REP(i,22) REP(j,22) REP(k,22) REP(l,22) dp[i][j][k][l] = -1;
  if(rec(0,0,h-1,w-1)>0) cout << "First" << endl;
  else cout << "Second" << endl;
  return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 4364
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int MAX_H = 22;
int dp[MAX_H][MAX_H][MAX_H][MAX_H];

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int H, W;
    cin >> H >> W;
    vector<string> S(H);
    for (auto& s : S) cin >> s;

    for (int i = 0; i < H; i++) {
        for (int j = i; j <= H; j++) {
            for (int k = 0; k < W; k++) {
                for (int l = k; l <= W; l++) {
                    dp[i][j][k][l] = -1;
                }
            }
        }
    }
    auto solve = [&](auto self, int lx, int rx, int ly, int ry) -> int {
        assert(lx <= rx && ly <= ry);
        if (lx == rx || ly == ry) return 0;
        if (~dp[lx][rx][ly][ry]) return dp[lx][rx][ly][ry];
        set<int> s;
        for (int x = lx; x < rx; x++) {
            for (int y = ly; y < ry; y++) {
                if (S[x][y] == 'X') continue;
                int a = self(self, lx, x, ly, y), b = self(self, x + 1, rx, ly, y), c = self(self, lx, x, y + 1, ry),
                    d = self(self, x + 1, rx, y + 1, ry);
                s.emplace(a ^ b ^ c ^ d);
            }
        }
        for (int i = 0;; i++) {
            if (!s.count(i)) {
                return dp[lx][rx][ly][ry] = i;
            }
        }
    };

    int ans = solve(solve, 0, H, 0, W);
    cout << (ans ? "First" : "Second") << '\n';
    return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 3960
final_rank: 3

code_snippet: #define LOCAL
#include <bits/stdc++.h>
using namespace std;
#pragma region Macros
typedef long long ll;
typedef __int128_t i128;
typedef unsigned int uint;
typedef unsigned long long ull;
#define ALL(x) (x).begin(), (x).end()

template <typename T> istream& operator>>(istream& is, vector<T>& v) {
    for (T& x : v) is >> x;
    return is;
}
template <typename T> ostream& operator<<(ostream& os, const vector<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const pair<T, U>& p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T, typename U> ostream& operator<<(ostream& os, const unordered_map<T, U>& m) {
    os << '{';
    for (auto itr = m.begin(); itr != m.end();) {
        os << '(' << itr->first << ',' << itr->second << ')';
        if (++itr != m.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const multiset<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const unordered_set<T>& s) {
    os << '{';
    for (auto itr = s.begin(); itr != s.end();) {
        os << *itr;
        if (++itr != s.end()) os << ',';
    }
    os << '}';
    return os;
}
template <typename T> ostream& operator<<(ostream& os, const deque<T>& v) {
    for (int i = 0; i < (int)v.size(); i++) {
        os << v[i] << (i + 1 == (int)v.size() ? "" : " ");
    }
    return os;
}

template <int i, typename T> void print_tuple(ostream&, const T&) {}
template <int i, typename T, typename H, class... Args> void print_tuple(ostream& os, const T& t) {
    if (i) os << ',';
    os << get<i>(t);
    print_tuple<i + 1, T, Args...>(os, t);
}
template <typename... Args> ostream& operator<<(ostream& os, const tuple<Args...>& t) {
    os << '{';
    print_tuple<0, tuple<Args...>, Args...>(os, t);
    return os << '}';
}

void debug_out() { cerr << '\n'; }
template <class Head, class... Tail> void debug_out(Head&& head, Tail&&... tail) {
    cerr << head;
    if (sizeof...(Tail) > 0) cerr << ", ";
    debug_out(move(tail)...);
}
#ifdef LOCAL
#define debug(...)                                                                   \
    cerr << " ";                                                                     \
    cerr << #__VA_ARGS__ << " :[" << __LINE__ << ":" << __FUNCTION__ << "]" << '\n'; \
    cerr << " ";                                                                     \
    debug_out(__VA_ARGS__)
#else
#define debug(...) 42
#endif

template <typename T> T gcd(T x, T y) { return y != 0 ? gcd(y, x % y) : x; }
template <typename T> T lcm(T x, T y) { return x / gcd(x, y) * y; }

int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(long long t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int botbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int botbit(long long a) { return a == 0 ? 64 : __builtin_ctzll(a); }
int popcount(signed t) { return __builtin_popcount(t); }
int popcount(long long t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x - y + 1) / y);
}

template <class T1, class T2> inline bool chmin(T1& a, T2 b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}
template <class T1, class T2> inline bool chmax(T1& a, T2 b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
#pragma endregion

const int INF = 1e9;
const long long IINF = 1e18;
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
const char dir[4] = {'D', 'R', 'U', 'L'};
const long long MOD = 1000000007;
// const long long MOD = 998244353;

const int MAX_H = 22;
int dp[MAX_H][MAX_H][MAX_H][MAX_H];

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int H, W;
    cin >> H >> W;
    vector<string> S(H);
    for (auto& s : S) cin >> s;

    for (int i = 0; i < H; i++) {
        for (int j = i; j <= H; j++) {
            for (int k = 0; k < W; k++) {
                for (int l = k; l <= W; l++) {
                    dp[i][j][k][l] = -1;
                }
            }
        }
    }
    auto solve = [&](auto self, int lx, int rx, int ly, int ry) -> int {
        assert(lx <= rx && ly <= ry);
        if (lx == rx || ly == ry) return 0;
        if (~dp[lx][rx][ly][ry]) return dp[lx][rx][ly][ry];
        set<int> s;
        for (int x = lx; x < rx; x++) {
            for (int y = ly; y < ry; y++) {
                if (S[x][y] == 'X') continue;
                int a = self(self, lx, x, ly, y), b = self(self, x + 1, rx, ly, y), c = self(self, lx, x, y + 1, ry),
                    d = self(self, x + 1, rx, y + 1, ry);
                s.emplace(a ^ b ^ c ^ d);
            }
        }
        for (int i = 0;; i++) {
            if (!s.count(i)) {
                return dp[lx][rx][ly][ry] = i;
            }
        }
    };

    int ans = solve(solve, 0, H, 0, W);
    cout << (ans ? "First" : "Second") << '\n';
    return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 3956
final_rank: 2

code_snippet: #pragma GCC target("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
//#include <atcoder/all>
using namespace std;
//using namespace atcoder;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-8;
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
const int mod = 1e9 + 7;
//const int mod = 998244353;

bool in(ll y, ll x, ll h, ll w){
    return 0 <= y && y < h && 0 <= x && x < w;
}

int g[22][22][22][22];
bool det[22][22][22][22];
vs s(22);
int h,w;

int f(int a, int b, int c, int d){
    if(a>=c || b>=d) return 0;
    if(det[a][b][c][d]) return g[a][b][c][d];
    det[a][b][c][d] = true;
    vl res;
    for(int i=a; i<c; i++) for(int j=b; j<d; j++){
        if(s[i][j] == 'X') continue; 
        res.push_back(f(a,b,i,j) ^ f(i+1,b,c,j) ^ f(a,j+1,i,d) ^ f(i+1,j+1,c,d));
    }
    vb me((int)res.size()+2,false);
    for(auto x : res) me[x] = true;
    rep(i,(int)res.size()+2){
        if(!me[i]) return g[a][b][c][d] = i;
    }
    assert(false);
    return -1;
}

int main(){
    cin >> h >> w;
    rep(i,h) cin >> s[i];
    if(f(0,0,h,w) > 0) cout << "First\n";
    else cout << "Second\n";
}
accuracy: 1
time_ms: 30
memory_kb: 4488
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main() {
  
  ios::sync_with_stdio(false);
  cin.tie(0);

  int h,w;
  cin >> h >> w;
  vector<vector<char>> s(h,vector<char>(w));
  for (int i=0;i<h;i++) {
    for (int j=0;j<w;j++) {
      cin >> s[i][j];
    }
  }
  vector<vector<vector<vector<int>>>> grundy(h+1,vector<vector<vector<int>>>(w+1,vector<vector<int>>(h+1,vector<int>(w+1,0))));
  for (int d=1;d<=h;d++) {
    for (int e=1;e<=w;e++) {
      for (int i=0;i+d<=h;i++) {
        for (int j=0;j+e<=w;j++) {
          // grundy[i][j][i+d][j+e]
          // [i,i+d)*[j,j+e)
          set<int> gs;
          for (int k=i;k<i+d;k++) {
            for (int l=j;l<j+e;l++) {
              if (s[k][l] == 'X') continue;
              int val = 0;
              val ^= grundy[i][j][k][l];
              val ^= grundy[k+1][j][i+d][l];
              val ^= grundy[i][l+1][k][j+e];
              val ^= grundy[k+1][l+1][i+d][j+e];
              gs.insert(val);
            }
          }
          int num = 0;
          while (gs.find(num) != gs.end()) {
            num++;
          }
          grundy[i][j][i+d][j+e] = num;
        }
      }
    }
  }
  if (grundy[0][0][h][w] == 0) cout << "Second" << endl;
  else cout << "First" << endl;
}
accuracy: 1
time_ms: 60
memory_kb: 4624
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main() {
  
  ios::sync_with_stdio(false);
  cin.tie(0);

  int h,w;
  cin >> h >> w;
  vector<vector<char>> s(h,vector<char>(w));
  for (int i=0;i<h;i++) {
    for (int j=0;j<w;j++) {
      cin >> s[i][j];
    }
  }
  vector<vector<vector<vector<int>>>> grundy(h+1,vector<vector<vector<int>>>(w+1,vector<vector<int>>(h+1,vector<int>(w+1,0))));
  for (int d=1;d<=h;d++) {
    for (int e=1;e<=w;e++) {
      for (int i=0;i+d<=h;i++) {
        for (int j=0;j+e<=w;j++) {
          // grundy[i][j][i+d][j+e]
          // [i,i+d)*[j,j+e)
          set<int> gs;
          for (int k=i;k<i+d;k++) {
            for (int l=j;l<j+e;l++) {
              if (s[k][l] == 'X') continue;
              int val = 0;
              val ^= grundy[i][j][k][l];
              val ^= grundy[k+1][j][i+d][l];
              val ^= grundy[i][l+1][k][j+e];
              val ^= grundy[k+1][l+1][i+d][j+e];
              gs.insert(val);
            }
          }
          int num = 0;
          while (gs.find(num) != gs.end()) {
            num++;
          }
          grundy[i][j][i+d][j+e] = num;
        }
      }
    }
  }
  if (grundy[0][0][h][w] == 0) cout << "Second" << endl;
  else cout << "First" << endl;
}
accuracy: 1
time_ms: 60
memory_kb: 4552
final_rank: 10

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 4000000000000000000 //オーバーフローに注意
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 25


int H,W;
int memo[SIZE][SIZE][SIZE][SIZE]; //memo[左上行][左上列][右下行][右下列] := grundy数のメモ
char table[SIZE][SIZE];


int grundy(int row1,int col1,int row2,int col2){

	if(row1 > row2 || col1 > col2){

		return 0;
	}

	if(memo[row1][col1][row2][col2] != -1){

		return memo[row1][col1][row2][col2];
	}

	set<int> SET;

	for(int row = row1; row <= row2; row++){
		for(int col = col1; col <= col2; col++){

			if(table[row][col] == 'X')continue;

			int tmp = 0;
			tmp ^= grundy(row1,col1,row-1,col-1); //左上
			tmp ^= grundy(row+1,col1,row2,col-1); //左下
			tmp ^= grundy(row1,col+1,row-1,col2); //右上
			tmp ^= grundy(row+1,col+1,row2,col2); //右下

			SET.insert(tmp);
		}
	}

	int ret = 0;

	while(SET.count(ret) > 0){

		ret++;
	}

	//printf("(%d,%d,%d,%d): %d\n",row1,col1,row2,col2,ret);

	return memo[row1][col1][row2][col2] = ret;
}


int main(){

	scanf("%d %d",&H,&W);

	for(int row = 0; row < H; row++){

		scanf("%s",table[row]);
	}

	for(int a = 0; a < H; a++){
		for(int b = 0; b < W; b++){
			for(int c = 0; c < H; c++){
				for(int d = 0; d < W; d++){

					memo[a][b][c][d] = -1;
				}
			}
		}
	}

	int ret = grundy(0,0,H-1,W-1);

	if(ret == 0){

		printf("Second\n");
	}else{

		printf("First\n");
	}

	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 4204
final_rank: 4